transformResponse method
As an agreement, we return the response when the
Options.responseType is ResponseType.stream.
Implementation
@override
Future<dynamic> transformResponse(
RequestOptions options,
ResponseBody response,
) async {
if (options.responseType == ResponseType.stream) {
return response;
}
int length = 0;
int received = 0;
final showDownloadProgress = options.onReceiveProgress != null;
if (showDownloadProgress) {
length = int.parse(
response.headers[Headers.contentLengthHeader]?.first ?? '-1',
);
}
final completer = Completer();
final stream = response.stream.transform<Uint8List>(
StreamTransformer.fromHandlers(
handleData: (data, sink) {
sink.add(data);
if (showDownloadProgress) {
received += data.length;
options.onReceiveProgress?.call(received, length);
}
},
),
);
// Keep references to the data chunks and concatenate them later.
final chunks = <Uint8List>[];
int finalSize = 0;
final StreamSubscription subscription = stream.listen(
(chunk) {
finalSize += chunk.length;
chunks.add(chunk);
},
onError: (Object error, StackTrace stackTrace) {
completer.completeError(error, stackTrace);
},
onDone: () => completer.complete(),
cancelOnError: true,
);
options.cancelToken?.whenCancel.then((_) {
return subscription.cancel();
});
await completer.future;
// Copy all chunks into a final Uint8List.
final responseBytes = Uint8List(finalSize);
int chunkOffset = 0;
for (final chunk in chunks) {
responseBytes.setAll(chunkOffset, chunk);
chunkOffset += chunk.length;
}
if (options.responseType == ResponseType.bytes) {
return responseBytes;
}
final String? responseBody;
if (options.responseDecoder != null) {
responseBody = options.responseDecoder!(
responseBytes,
options,
response..stream = Stream.empty(),
);
} else if (responseBytes.isNotEmpty) {
responseBody = utf8.decode(responseBytes, allowMalformed: true);
} else {
responseBody = null;
}
if (responseBody != null &&
responseBody.isNotEmpty &&
options.responseType == ResponseType.json &&
Transformer.isJsonMimeType(
response.headers[Headers.contentTypeHeader]?.first,
)) {
return jsonDecodeCallback(responseBody);
}
return responseBody;
}