uploadFileInShards method

Future<String> uploadFileInShards({
  1. required Uint8List bytes,
  2. required String fileName,
  3. bool enforceChatFileLimit = true,
  4. CancelToken? cancelToken,
  5. void onProgress(
    1. double progress
    )?,
})

完整大文件分片上传(对齐 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;
}