uploadBlob method

Future<BlobUploadResult> uploadBlob(
  1. BlobFile file
)

Uploads a single attachment with retries.

Implementation

Future<BlobUploadResult> uploadBlob(BlobFile file) {
  const label = 'attachment upload';
  final url = Uri.parse(
    '${config.baseURL}/projects/${config.projectId}/blobs',
  );
  return withUploadRetry('$label (${file.fileName})', () async {
    final MultipartBody body;
    try {
      body = openMultipart(file);
    } on FileSystemException catch (error) {
      throw ApiError('$label failed: $error', retryable: false);
    }
    final _Response response;
    try {
      response = await _send(
        'POST',
        url,
        headers: <String, String>{
          'Authorization': 'Bearer ${config.token}',
          'Content-Type': body.contentType,
        },
        bodyStream: body.stream,
        contentLength: body.length,
        timeout: httpUploadTimeout,
      );
    } on FileSystemException catch (error) {
      throw ApiError('$label failed: $error', retryable: false);
    } on Object catch (error) {
      throw ApiError('$label failed: $error');
    }
    if (response.statusCode >= 400) {
      throw ApiError(
        '$label failed: HTTP ${response.statusCode} ${response.body.trim()}',
      );
    }
    final json = _decodeObject(response.body, label);
    final fileName = json['fileName'];
    final mimeType = json['mimeType'];
    final sizeBytes = json['sizeBytes'];
    return BlobUploadResult(
      id: (json['id'] as String?) ?? '',
      fileName: fileName is String && fileName.isNotEmpty
          ? fileName
          : file.fileName,
      mimeType: mimeType is String && mimeType.isNotEmpty
          ? mimeType
          : (file.mimeType.isEmpty ? defaultMimeType : file.mimeType),
      sizeBytes: sizeBytes is int ? sizeBytes : 0,
    );
  });
}