downloadWithProgress method
Implementation
Future<DownloadProgress> downloadWithProgress({
required String url,
required String filename,
required Function(double) onProgress,
Function(int)? onSpeed,
Function(int)? onComplete,
}) async {
final cancelToken = CancelToken();
_cancelTokens[url] = cancelToken;
try {
final filePath = await _getDownloadPath(filename);
debugPrint('📥 Downloading: $url');
debugPrint('📥 To: $filePath');
int lastReceived = 0;
DateTime lastTime = DateTime.now();
final startTime = DateTime.now();
await _dio.download(
url,
filePath,
cancelToken: cancelToken,
onReceiveProgress: (received, total) {
if (total != -1) {
final progress = received / total;
onProgress(progress);
// Calculate speed
final now = DateTime.now();
final timeDiff = now.difference(lastTime).inMilliseconds;
if (timeDiff >= 500 && onSpeed != null) {
final bytesDiff = received - lastReceived;
final speed = (bytesDiff * 1000 / timeDiff)
.round(); // bytes per second
onSpeed(speed);
lastReceived = received;
lastTime = now;
}
}
},
);
// Calculate total download time
final totalTime = DateTime.now().difference(startTime).inSeconds;
if (onComplete != null) {
onComplete(totalTime);
}
return DownloadProgress(
state: DownloadState.completed,
progress: 1.0,
filePath: filePath,
);
} on DioException catch (e) {
if (e.type == DioExceptionType.cancel) {
return DownloadProgress(
state: DownloadState.idle,
error: 'Download cancelled',
);
}
return DownloadProgress(
state: DownloadState.failed,
error: e.message ?? 'Download failed',
);
} catch (e) {
return DownloadProgress(state: DownloadState.failed, error: e.toString());
} finally {
_cancelTokens.remove(url);
}
}