postMultipart<ResponseType> method

Future<ResponseType> postMultipart<ResponseType>(
  1. String path, {
  2. required Iterable<MultipartFile> files,
  3. Map<String, String>? headers,
  4. JsonDeserializer<ResponseType>? responseDeserializer,
  5. UploadProgressCallback? onUploadProgress,
})

Performs an HTTP POST multipart api call.

path is appended to baseUrl to determine the API endpoint.

The return value is the result of passing the response's JSON-decoded body to responseDeserializer. If responseDeserializer is null, null will be returned.

Implementation

Future<ResponseType> postMultipart<ResponseType>(
  String path, {
  required Iterable<http.MultipartFile> files,
  Map<String, String>? headers,
  JsonDeserializer<ResponseType>? responseDeserializer,
  UploadProgressCallback? onUploadProgress,
}) async {
  final url = baseUrl.extend(path);
  final multipartRequest = http.MultipartRequest('post', url)
    ..files.addAll(files);

  http.BaseRequest requestToSend;
  if (onUploadProgress != null) {
    final chunkedByteStream = chunkStream(
      multipartRequest.finalize(),
      chunkLength: multipartChunkSize,
    );

    // Reporting upload progress isn't straightforward, so we have to jump
    // through a few hoops to get it going.
    //
    // The central idea is that we create the stream representation of the
    // request, set ourselves up to watch the stream's consumption rate, then
    // send it over the wire. The consumed bytes are reported to the callback
    // as the upload progress.
    var bytesUploaded = 0;
    final bytesTotal = multipartRequest.contentLength;
    final observedByteStream = chunkedByteStream
        .transform(StreamTransformer<List<int>, List<int>>.fromHandlers(
      handleData: (data, sink) {
        // Pass the data along the chain
        sink.add(data);

        // ...and report progress
        bytesUploaded += data.length;
        onUploadProgress(multipartRequest, bytesUploaded, bytesTotal);
      },
      handleError: (error, stackTrace, sink) =>
          throw AsyncError(error, stackTrace),
      handleDone: (sink) => sink.close(),
    ));

    requestToSend = StreamWrappingRequest('post', url, observedByteStream)
      ..contentLength = multipartRequest.contentLength
      ..headers.addAll(multipartRequest.headers);
  } else {
    requestToSend = multipartRequest;
  }

  return send<ResponseType>(
    requestToSend,
    headers: headers,
    responseDeserializer: responseDeserializer,
  );
}