初始化
This commit is contained in:
81
lib/core/utils/transfer/download.dart
Normal file
81
lib/core/utils/transfer/download.dart
Normal file
@@ -0,0 +1,81 @@
|
||||
//下载文件
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
|
||||
class LocalDownload {
|
||||
static Future<String> getLocalFilePath(String url, String path) async {
|
||||
Uri uri = Uri.parse(url);
|
||||
String fileName = uri.pathSegments.last;
|
||||
//获取下载目录
|
||||
Directory dir = await getApplicationCacheDirectory();
|
||||
Directory uploadPath = Directory("${dir.path}$path/");
|
||||
return uploadPath.path + fileName;
|
||||
}
|
||||
|
||||
/// 公用下载方法
|
||||
/// url 下载网络地址
|
||||
/// path 存储地址,如/test
|
||||
/// onProgress 下载回调函数
|
||||
/// onDone 下载完毕回调
|
||||
static downLoadFile({
|
||||
required url,
|
||||
required path,
|
||||
required Function(double) onProgress,
|
||||
required Function(String) onDone,
|
||||
}) async {
|
||||
HttpClient client = HttpClient();
|
||||
Uri uri = Uri.parse(url);
|
||||
//获取本地文件路径
|
||||
String filePath = await getLocalFilePath(url, path);
|
||||
// 发起 get 请求
|
||||
HttpClientRequest request = await client.getUrl(uri);
|
||||
// 响应
|
||||
HttpClientResponse response = await request.close();
|
||||
int contentLength = response.contentLength; // 获取文件总大小
|
||||
int bytesReceived = 0; // 已接收的字节数
|
||||
List<int> chunkList = [];
|
||||
if (response.statusCode == 200) {
|
||||
response.listen(
|
||||
(List<int> chunk) {
|
||||
chunkList.addAll(chunk);
|
||||
bytesReceived += chunk.length; //更新已接受的字节数
|
||||
//进度
|
||||
double progress = bytesReceived * 100 / contentLength * 100;
|
||||
progress = (progress / 100).truncateToDouble();
|
||||
onProgress(progress);
|
||||
},
|
||||
onDone: () async {
|
||||
//下载完毕
|
||||
client.close();
|
||||
File file = File(filePath);
|
||||
if (!file.existsSync()) {
|
||||
file.createSync(recursive: true);
|
||||
await file.writeAsBytes(chunkList);
|
||||
}
|
||||
onDone(file.path);
|
||||
},
|
||||
onError: () {
|
||||
client.close();
|
||||
},
|
||||
cancelOnError: true,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
///获取本地地址
|
||||
///
|
||||
static Future<String> getFilePath({
|
||||
required url,
|
||||
required path,
|
||||
}) async {
|
||||
//获取本地文件路径
|
||||
String filePath = await getLocalFilePath(url, path);
|
||||
File file = File(filePath);
|
||||
if (file.existsSync()) {
|
||||
return file.path;
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
}
|
||||
46
lib/core/utils/transfer/file_type.dart
Normal file
46
lib/core/utils/transfer/file_type.dart
Normal file
@@ -0,0 +1,46 @@
|
||||
enum FileType {
|
||||
image,
|
||||
pdf,
|
||||
other,
|
||||
}
|
||||
|
||||
class FileMeta {
|
||||
final String name; // 不含后缀
|
||||
final String extension; // 不含点
|
||||
final FileType type;
|
||||
|
||||
const FileMeta({
|
||||
required this.name,
|
||||
required this.extension,
|
||||
required this.type,
|
||||
});
|
||||
}
|
||||
|
||||
FileMeta parseFileMeta(String path) {
|
||||
final uri = Uri.parse(path);
|
||||
final fileName = uri.pathSegments.isNotEmpty ? uri.pathSegments.last : '';
|
||||
|
||||
if (!fileName.contains('.')) {
|
||||
return const FileMeta(
|
||||
name: '',
|
||||
extension: '',
|
||||
type: FileType.other,
|
||||
);
|
||||
}
|
||||
|
||||
final index = fileName.lastIndexOf('.');
|
||||
final name = fileName.substring(0, index);
|
||||
final ext = fileName.substring(index + 1).toLowerCase();
|
||||
|
||||
final type = switch (ext) {
|
||||
'jpg' || 'jpeg' || 'png' || 'webp' || 'gif' => FileType.image,
|
||||
'pdf' => FileType.pdf,
|
||||
_ => FileType.other,
|
||||
};
|
||||
|
||||
return FileMeta(
|
||||
name: name,
|
||||
extension: ext,
|
||||
type: type,
|
||||
);
|
||||
}
|
||||
70
lib/core/utils/transfer/select_file.dart
Normal file
70
lib/core/utils/transfer/select_file.dart
Normal file
@@ -0,0 +1,70 @@
|
||||
import 'dart:io';
|
||||
import 'package:file_picker/file_picker.dart';
|
||||
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
||||
import 'package:flutter_image_compress/flutter_image_compress.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
|
||||
/// 选择文件
|
||||
/// - [type] 文件类型
|
||||
/// - [allowedExtensions] 允许的扩展名
|
||||
/// - [maxSize] 最大文件大小
|
||||
Future<List<File>> selectFile({
|
||||
required FileType type,
|
||||
List<String>? allowedExtensions,
|
||||
int maxSize = 1024 * 1024 * 20,
|
||||
}) async {
|
||||
List<File> files = [];
|
||||
bool hasOversize = false;
|
||||
|
||||
FilePickerResult? result = await FilePicker.platform.pickFiles(
|
||||
type: type,
|
||||
allowedExtensions: allowedExtensions,
|
||||
);
|
||||
// 判断空
|
||||
if (result == null) return [];
|
||||
|
||||
//进行文件大小,压缩、等操作
|
||||
for (final e in result.files) {
|
||||
if (e.size > maxSize) {
|
||||
hasOversize = true;
|
||||
continue;
|
||||
}
|
||||
if (e.path == null) continue;
|
||||
|
||||
if (type == FileType.image) {
|
||||
final compressed = await compressImage(File(e.path!));
|
||||
files.add(compressed);
|
||||
} else {
|
||||
files.add(File(e.path!));
|
||||
}
|
||||
}
|
||||
//提示
|
||||
if (hasOversize) {
|
||||
EasyLoading.showInfo('已过滤超过 20MB 的文件');
|
||||
}
|
||||
return files;
|
||||
}
|
||||
|
||||
/// 压缩图片
|
||||
Future<File> compressImage(File file) async {
|
||||
final dir = await getTemporaryDirectory();
|
||||
final targetPath = p.join(
|
||||
dir.path,
|
||||
'${DateTime.now().millisecondsSinceEpoch}.jpg',
|
||||
);
|
||||
|
||||
final result = await FlutterImageCompress.compressAndGetFile(
|
||||
file.absolute.path,
|
||||
targetPath,
|
||||
quality: 80,
|
||||
format: CompressFormat.jpeg,
|
||||
minWidth: 1080,
|
||||
minHeight: 1080,
|
||||
);
|
||||
|
||||
if (result == null) {
|
||||
throw Exception('Image compression failed');
|
||||
}
|
||||
return File(result.path);
|
||||
}
|
||||
59
lib/core/utils/transfer/upload.dart
Normal file
59
lib/core/utils/transfer/upload.dart
Normal file
@@ -0,0 +1,59 @@
|
||||
import 'dart:io';
|
||||
import 'package:app/data/api/common_api.dart';
|
||||
import 'package:app/data/models/common/qiu_token_dto.dart';
|
||||
import 'package:crypto/crypto.dart';
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
||||
|
||||
import '../../config/global.dart';
|
||||
|
||||
class QinUpload {
|
||||
///获取七牛token
|
||||
static Future<QiuTokenDto> _getQiuToken(File file, String path) async {
|
||||
// 读取文件的字节数据
|
||||
final fileBytes = await file.readAsBytes();
|
||||
String fileMd5 = md5.convert(fileBytes).toString();
|
||||
//前缀
|
||||
var prefix = Config.getEnv() == "dev" ? "test" : "release";
|
||||
var suffix = file.path.split(".").last;
|
||||
|
||||
var res = await getQiuTokenApi(
|
||||
"shangyiapp/$prefix/$path/$fileMd5.$suffix",
|
||||
);
|
||||
return res;
|
||||
}
|
||||
|
||||
///上传文件
|
||||
/// - [file] 文件
|
||||
/// - [path] 目标目录,不以/开头和结尾
|
||||
static Future<String?> upload({
|
||||
required File file,
|
||||
required String path,
|
||||
|
||||
}) async {
|
||||
var qiuToken = await _getQiuToken(file, path);
|
||||
//数据
|
||||
FormData formData = FormData.fromMap({
|
||||
"file": await MultipartFile.fromFile(file.path),
|
||||
"token": qiuToken.upToken,
|
||||
"fname": qiuToken.fileKey,
|
||||
"key": qiuToken.fileKey,
|
||||
});
|
||||
try {
|
||||
Dio dio = Dio();
|
||||
Response response = await dio.post(
|
||||
qiuToken.uploadUrl!,
|
||||
data: formData,
|
||||
onSendProgress: (int sent, int total) {
|
||||
// double progress = sent * 100 / total * 100;
|
||||
// progress = (progress / 100).truncateToDouble();
|
||||
},
|
||||
);
|
||||
String key = response.data['key'];
|
||||
return "https://${qiuToken.domain}/$key";
|
||||
} catch (e) {
|
||||
EasyLoading.showError("上传失败");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user