3.dart_ 2.16 KB
class MultiThreadedFileUploader {
  static const int CHUNK_SIZE = 1024 * 1024; // 1MB
  static const int MAX_CONCURRENT_UPLOADS = 3;
  
  final ParallelUploader _uploader = ParallelUploader(
    maxConcurrentUploads: MAX_CONCURRENT_UPLOADS
  );
  
  // 主上传方法
  Future<UploadSummary> uploadFile(
    File file, 
    String uploadUrl,
    String mergeUrl,
  ) async {
    final stopwatch = Stopwatch()..start();
    
    try {
      print('开始准备分片...');
      
      // 在后台线程计算分片
      final chunks = await FileUploader.prepareChunks(file, CHUNK_SIZE);
      print('文件分片完成,共 ${chunks.length} 个分片');
      
      // 并行上传所有分片
      print('开始并行上传分片...');
      final results = await _uploader.uploadChunksParallel(
        file, chunks, uploadUrl
      );
      
      // 检查上传结果
      final failedChunks = results.where((r) => !r.success).toList();
      if (failedChunks.isNotEmpty) {
        throw Exception('部分分片上传失败: ${failedChunks.length}');
      }
      
      // 通知服务端合并文件
      print('所有分片上传完成,开始合并...');
      await _notifyMerge(file, chunks, mergeUrl);
      
      stopwatch.stop();
      
      return UploadSummary(
        success: true,
        totalChunks: chunks.length,
        fileSize: await file.length(),
        duration: stopwatch.elapsed,
      );
      
    } catch (e) {
      stopwatch.stop();
      return UploadSummary(
        success: false,
        error: e.toString(),
        duration: stopwatch.elapsed,
      );
    }
  }
  
  Future<void> _notifyMerge(
    File file, 
    List<ChunkInfo> chunks, 
    String mergeUrl
  ) async {
    final dio = Dio();
    await dio.post(mergeUrl, data: {
      'fileName': file.path.split('/').last,
      'totalChunks': chunks.length,
      'fileSize': await file.length(),
    });
  }
}

class UploadSummary {
  final bool success;
  final int? totalChunks;
  final int? fileSize;
  final Duration duration;
  final String? error;
  
  UploadSummary({
    required this.success,
    this.totalChunks,
    this.fileSize,
    required this.duration,
    this.error,
  });
}