download method
Future<AdapterResponse>
download(
- AdapterRequest request,
- String savePath, {
- ProgressCallback? onProgress,
override
Downloads a file from the server.
This method downloads a file and saves it to the specified path on the device.
Progress can be tracked using the optional onProgress callback.
Parameters:
request: The request configuration for the downloadsavePath: The local file path where the downloaded file will be savedonProgress: Optional callback to track download progress
Returns a Future that completes with an AdapterResponse when the download is complete.
Throws AdapterException if the download fails.
Example:
final request = AdapterRequest(
baseUrl: 'https://example.com',
path: '/files/document.pdf',
method: HttpMethod.get,
);
await adapter.download(
request,
'/path/to/save/document.pdf',
onProgress: (count, total) {
print('Downloaded: ${(count / total * 100).toStringAsFixed(1)}%');
},
);
Implementation
@override
Future<AdapterResponse> download(
AdapterRequest request,
String savePath, {
ProgressCallback? onProgress,
}) async {
final completer = Completer<void>();
try {
final baseRequest = await _buildBaseRequest(request);
if (request.cancelToken != null) {
_registerCancelToken(request.cancelToken!, completer);
if (request.cancelToken!.isCancelled) {
throw AdapterException.cancel(
message: request.cancelToken!.cancelReason,
);
}
}
final requestFuture = _client.send(baseRequest);
final streamedResponse = request.cancelToken != null
? await Future.any<http.StreamedResponse>([
requestFuture,
completer.future.then((_) => throw AdapterException.cancel(
message: request.cancelToken!.cancelReason,
)),
])
: await requestFuture;
if (streamedResponse.statusCode >= 400) {
throw AdapterException(
message: 'HTTP ${streamedResponse.statusCode}',
type: AdapterExceptionType.response,
statusCode: streamedResponse.statusCode,
response: _convertFromHttpStreamedResponse(streamedResponse, request),
);
}
if (kIsWeb) {
throw AdapterException(
message:
'File download is not supported on Web platform. Use browser download API instead.',
type: AdapterExceptionType.unknown,
);
}
final file = File(savePath);
if (!file.parent.existsSync()) {
file.parent.createSync(recursive: true);
}
final sink = file.openWrite();
try {
var received = 0;
final total = streamedResponse.contentLength ?? -1;
await for (final chunk in _bindCancelToken(
streamedResponse.stream,
request.cancelToken,
)) {
sink.add(chunk);
received += chunk.length;
onProgress?.call(received, total > 0 ? total : received);
}
} finally {
await sink.flush();
await sink.close();
}
final responseHeaders = <String, List<String>>{};
streamedResponse.headers.forEach((key, value) {
responseHeaders[key] = [value];
});
return AdapterResponse(
statusCode: streamedResponse.statusCode,
statusMessage: streamedResponse.reasonPhrase,
data: savePath,
headers: responseHeaders,
request: request,
);
} catch (e, stackTrace) {
if (e is AdapterException) {
rethrow;
}
throw _convertException(e, stackTrace);
} finally {
_unregisterCancelToken(request.cancelToken, completer);
}
}