postMultipart<ResponseType> method
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,
);
}