From 498bb0e5fb42d5f2741fe43c0e12e30f42014d6a Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Wed, 21 Aug 2024 09:33:34 +0800 Subject: [PATCH] :zap: Run upload chunks at the same time (max 3) --- lib/providers/attachment_uploader.dart | 52 ++++++++++++++++++-------- 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/lib/providers/attachment_uploader.dart b/lib/providers/attachment_uploader.dart index 9945ee9..86d7f0e 100644 --- a/lib/providers/attachment_uploader.dart +++ b/lib/providers/attachment_uploader.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'dart:collection'; import 'dart:typed_data'; import 'package:cross_file/cross_file.dart'; @@ -199,25 +200,44 @@ class AttachmentUploaderController extends GetxController { final filename = basename(file.path); final chunks = holder.meta.fileChunks ?? {}; var currentTask = 0; + + final queue = Queue>(); + final activeTasks = >[]; + for (final entry in chunks.entries) { - final beginCursor = entry.value * holder.chunkSize; - final endCursor = (entry.value + 1) * holder.chunkSize; - final data = Uint8List.fromList(await file - .openRead(beginCursor, endCursor) - .expand((chunk) => chunk) - .toList()); + queue.add(() async { + final beginCursor = entry.value * holder.chunkSize; + final endCursor = (entry.value + 1) * holder.chunkSize; + final data = Uint8List.fromList(await file + .openRead(beginCursor, endCursor) + .expand((chunk) => chunk) + .toList()); - final out = await attach.uploadAttachmentMultipartChunk( - data, - filename, - holder.meta.rid, - entry.key, - ); - holder.meta = out; + final out = await attach.uploadAttachmentMultipartChunk( + data, + filename, + holder.meta.rid, + entry.key, + ); + holder.meta = out; - currentTask++; - onProgress(currentTask / chunks.length); - onData(holder); + currentTask++; + onProgress(currentTask / chunks.length); + onData(holder); + }()); + } + + while (queue.isNotEmpty || activeTasks.isNotEmpty) { + while (activeTasks.length < 3 && queue.isNotEmpty) { + final task = queue.removeFirst(); + activeTasks.add(task); + + task.then((_) => activeTasks.remove(task)); + } + + if (activeTasks.isNotEmpty) { + await Future.any(activeTasks); + } } return holder.meta;