breakPointUpload method

void breakPointUpload({
  1. required String filePath,
  2. ProgressCallback? onSendProgress,
  3. Success? success,
  4. Failure? failure,
  5. Completed? completed,
  6. dynamic cancelCallback()?,
  7. int? start,
})

断点上传

Implementation

void breakPointUpload({
  required String filePath,
  adapter.ProgressCallback? onSendProgress,
  Success? success,
  Failure? failure,
  Completed? completed,
  Function()? cancelCallback,
  int? start,
}) async {
  if (!(await _checkNetWork())) {
    return;
  }

  final url = _buildFinalUrl();
  final payload = _resolveRequestPayload();
  final file = File(filePath);

  try {
    if (!file.existsSync()) {
      throw FileSystemException('Upload file does not exist', filePath);
    }

    final fileSize = file.lengthSync();
    var progress = start ?? 0;
    if (progress < 0 || progress > fileSize) {
      throw RangeError.range(progress, 0, fileSize, 'start');
    }

    if (progress > 0) {
      onSendProgress?.call(progress, fileSize);
    }

    if (progress == fileSize) {
      onSendProgress?.call(fileSize, fileSize);
      success?.call(file, SourcesType.net);
      return;
    }

    // 添加 Content-Range 头部
    final headers = _buildHeaders();
    headers[HttpHeaders.contentLengthHeader] = '${fileSize - progress}';
    headers['Content-Range'] = 'bytes $progress-${fileSize - 1}/$fileSize';

    final data = _trackUploadProgress(
      file.openRead(progress, fileSize),
      onChunk: (chunkLength) {
        progress += chunkLength;
        onSendProgress?.call(progress, fileSize);
      },
    );

    // 构建 AdapterRequest,内部会复用统一参数解析逻辑
    final adapterRequest = _buildAdapterRequest(
      url: url,
      queryParams: payload.queryParams,
      data: data,
      headers: headers,
      contentType: payload.contentType,
    );

    // 使用适配器发送请求
    final adapter = _requireAdapter();
    final response = await adapter.request(adapterRequest);
    onResponse?.call(response);

    final responseStream = _extractByteStream(response.data);
    if (responseStream != null) {
      try {
        await responseStream.drain<void>();
      } catch (error) {
        if (_isCancelledStreamError(error)) {
          cancelCallback?.call();
          return;
        }
        rethrow;
      }
    }

    if (response.isSuccess) {
      success?.call(file, SourcesType.net);
    } else {
      failure?.call(response.data);
    }
  } on AdapterException catch (error) {
    if (error.type == AdapterExceptionType.cancel) {
      cancelCallback?.call();
    } else {
      failure?.call(error);
    }
  } catch (e) {
    failure?.call(e);
  } finally {
    completed?.call();
  }
}