import 'package:dio/dio.dart'; import 'package:file_picker/file_picker.dart'; import 'fileUtils.dart'; const _show_debug_info = true; /// 上传状态枚举 enum UploadStatus { uploading, completed, failed, } /// 上传结果 class UploadResult { final UploadStatus status; final String? filePath; final double? progress; final int? errorCode; final String? errorReason; bool get isCompleted => status == UploadStatus.completed; bool get isUploading => status == UploadStatus.uploading; bool get isFailed => status == UploadStatus.failed; /// ----- error code ----- static const int errorCodeError = -1; static const int errorCodeUserCancel = 1; static const int errorCodeFileIsNotExist = -2; /// ----- constructor ----- UploadResult({ required this.status, this.filePath, this.progress, this.errorCode, this.errorReason, }); factory UploadResult.uploading(double progress) { if (progress < 0) { progress = 0; } else if (progress > 1) { progress = 1; } return UploadResult( status: UploadStatus.uploading, progress: progress, ); } factory UploadResult.failed({ int errorCode = errorCodeError, String? errorReason, }) { return UploadResult( status: UploadStatus.failed, errorCode: errorCode, errorReason: errorReason, ); } factory UploadResult.completed({ required String filePath, }) { return UploadResult( status: UploadStatus.completed, filePath: filePath, progress: 1.0, ); } } class HttpDownloader { //上传 static Future upload({ required String receiverUrl, String? filePath, void Function(UploadResult)? onProgress, }) async { // 选择文件 String selectedFilePath; if (filePath != null) { if (await isFileExists(filePath)) { selectedFilePath = filePath; } else { final result = UploadResult.failed( errorCode: UploadResult.errorCodeFileIsNotExist, errorReason: 'file is not exist', ); if (onProgress != null) { onProgress(result); } return result; } } else { FilePickerResult? result = await FilePicker.platform.pickFiles(); if (result == null) { final result = UploadResult.failed( errorCode: UploadResult.errorCodeUserCancel, errorReason: 'Selection canceled by user', ); if (onProgress != null) { onProgress(result); } return result; } PlatformFile file = result.files.first; selectedFilePath = file.path!; } FormData formData = FormData.fromMap({ "file": await MultipartFile.fromFile(selectedFilePath), }); final dio = Dio(); try { if (_show_debug_info) { print('┌────────────────────────────────────────────────────────────────────────────────────────'); print('│ ⬆️ start upload file: $selectedFilePath'); print('└────────────────────────────────────────────────────────────────────────────────────────'); } final response = await dio.post( receiverUrl, data: formData, onSendProgress: (sent, total) { if (_show_debug_info) { print('upload: $sent / $total'); } if (onProgress != null) { onProgress(UploadResult.uploading(sent / (total * 100))); } }, ); if (_show_debug_info) { print('$filePath 上传完成: $response.data'); } final result = UploadResult.completed(filePath: selectedFilePath); if (onProgress != null) { onProgress(result); } return result; } catch (e) { print('上传失败: $e'); final result = UploadResult.failed( errorReason: e.toString(), ); if (onProgress != null) { onProgress(result); } return result; } } }