download method
Future<Result<File> >
download(
- String url, {
- required String savePath,
- ProgressCallback? onProgress,
- RequestOptions? options,
override
Standard one-shot file download.
Implementation
@override
Future<Result<File>> download(
String url, {
required String savePath,
ProgressCallback? onProgress,
RequestOptions? options,
}) async {
final uri = Uri.parse(url);
HttpClientRequest req;
try {
req = await _http
.getUrl(uri)
.timeout(
options?.timeout ?? _config.timeout,
onTimeout: () =>
throw TimeoutException('Download from $url timed out'),
);
} on SocketException catch (e) {
return Failure(ConnectionException('Cannot reach ${uri.host}', cause: e));
}
(options?.headers ?? {}).forEach(req.headers.set);
late HttpClientResponse response;
try {
response = await req.close();
} catch (e) {
return Failure(
UnknownNetworkException('Download request failed: $e', cause: e),
);
}
if (response.statusCode < 200 || response.statusCode >= 300) {
final body = await _readBody(response);
return Failure(
HttpStatusException(
statusCode: response.statusCode,
message: 'Download failed with HTTP ${response.statusCode}',
responseBody: body,
),
);
}
final total = response.contentLength; // -1 if unknown
var received = 0;
final output = File(savePath);
final sink = output.openWrite();
try {
await for (final chunk in response) {
sink.add(chunk);
received += chunk.length;
if (total > 0) onProgress?.call(received, total);
}
} finally {
await sink.flush();
await sink.close();
}
return Success(output, statusCode: response.statusCode);
}