downloadFile method
Download file from URL
Implementation
Future<DownloadResult> downloadFile({
required String url,
String? savePath,
String? filename,
Map<String, dynamic>? headers,
Function(int received, int total)? onProgress,
CancelToken? cancelToken,
}) async {
try {
// Determine save path
final filePath = await _determineFilePath(savePath, filename, url);
// Create cancel token if not provided
final token = cancelToken ?? CancelToken();
// Store active download
_activeDownloads[url] = token;
// Log download start
_logger.log('📥 Starting download: $url');
_logger.log('💾 Save path: $filePath');
final startTime = DateTime.now();
// Download file
await _dio.download(
url,
filePath,
options: Options(
headers: {
..._config.globalHeaders,
if (headers != null) ...headers,
},
receiveTimeout: _config.receiveTimeout,
),
cancelToken: token,
onReceiveProgress: (received, total) {
// Call progress callback
onProgress?.call(received, total);
// Log progress
if (_config.enableLogs && total != -1) {
_logger.logDownloadProgress(
url: url,
received: received,
total: total,
);
}
},
deleteOnError: true,
);
// Remove from active downloads
_activeDownloads.remove(url);
final duration = DateTime.now().difference(startTime);
final file = File(filePath);
final fileSize = file.lengthSync();
_logger.log(
'✅ Download completed in ${duration.inMilliseconds}ms | Size: ${_formatBytes(fileSize)}',
);
return DownloadResult(
success: true,
filePath: filePath,
fileSize: fileSize,
duration: duration,
);
} on DioException catch (e) {
_activeDownloads.remove(url);
if (e.type == DioExceptionType.cancel) {
_logger.log('Download cancelled: $url', isError: true);
return DownloadResult(
success: false,
error: 'Download cancelled',
);
}
_logger.log('Download failed: ${e.message}', isError: true);
return DownloadResult(
success: false,
error: e.message ?? 'Download failed',
);
} catch (e) {
_activeDownloads.remove(url);
_logger.log('Download failed: $e', isError: true);
return DownloadResult(
success: false,
error: e.toString(),
);
}
}