uploadFileInShards method
完整大文件分片上传(对齐 Web uploadsStore.initUploadFile + 串行 triggerUpload)。
返回最终 uploadId,可用于发文件消息 body: { upload_id }。
onProgress 取值 0.0–1.0。
Implementation
Future<String> uploadFileInShards({
required Uint8List bytes,
required String fileName,
bool enforceChatFileLimit = true,
CancelToken? cancelToken,
void Function(double progress)? onProgress,
}) async {
if (enforceChatFileLimit && bytes.length > maxChatFileBytes) {
throw GoChatException('聊天文件不能超过 100MB');
}
final init = await initMultipart(
fileName: fileName,
fileSize: bytes.length,
cancelToken: cancelToken,
);
final shardSize =
init.shardSize > 0 ? init.shardSize : defaultShardSize;
final splitNum = init.shardNum > 0
? init.shardNum
: ((bytes.length + shardSize - 1) ~/ shardSize);
GoChatLogger.d(
'uploadFileInShards id=${init.uploadId} size=${bytes.length} '
'shard=$shardSize num=$splitNum',
);
UploadMultipartResult? last;
for (var i = 0; i < splitNum; i++) {
if (cancelToken?.isCancelled ?? false) {
throw GoChatException('上传已取消', code: -2);
}
final start = i * shardSize;
final end = (start + shardSize > bytes.length)
? bytes.length
: start + shardSize;
final chunk = Uint8List.sublistView(bytes, start, end);
last = await uploadMultipartShard(
uploadId: init.uploadId,
splitIndex: i + 1,
splitNum: splitNum,
bytes: chunk,
filename: fileName,
cancelToken: cancelToken,
);
onProgress?.call((i + 1) / splitNum);
}
if (last == null || !last.isMerge) {
GoChatLogger.e(
'uploadFileInShards finished without is_merge=true '
'id=${init.uploadId}',
);
}
return init.uploadId;
}