Handle incorrect pause

This commit is contained in:
Neeraj Gupta
2025-06-06 11:37:07 +05:30
parent 9245af5080
commit 14da860973

View File

@@ -22,6 +22,7 @@ class DownloadManager {
final Map<int, Completer<DownloadResult>> _completers = {};
final Map<int, StreamController<DownloadTask>> _streams = {};
final Map<int, CancelToken> _cancelTokens = {};
final Map<int, int> _downloadStartTimes = {};
DownloadManager(this._dio);
@@ -44,6 +45,7 @@ class DownloadManager {
String filename,
int totalBytes,
) async {
_downloadStartTimes[fileId] = DateTime.now().microsecondsSinceEpoch;
// If already downloading, return existing future
if (_completers.containsKey(fileId)) {
return _completers[fileId]!.future;
@@ -97,6 +99,15 @@ class DownloadManager {
/// Pause download
Future<void> pause(int fileId) async {
// ignore cancel if download started less than 1 second ago,
// this is to avoid cancellination due to different type of video players, where dispose is called
// little later after other video player operations
final startTime = _downloadStartTimes[fileId];
if (startTime == null ||
DateTime.now().microsecondsSinceEpoch - startTime < 1e6) {
_logger.info('Download paused too soon, ignoring pause request');
return;
}
final token = _cancelTokens[fileId];
if (token != null && !token.isCancelled) {
token.cancel('paused');
@@ -151,6 +162,31 @@ class DownloadManager {
final directory = Configuration.instance.getTempDirectory();
final basePath = '$directory${task.id}.encrypted';
// check if base file already exists and is of correct size
final baseFile = File(basePath);
if (await baseFile.exists()) {
final existingSize = await baseFile.length();
if (existingSize == task.totalBytes) {
_logger.info(
'Download already exists for ${task.filename} (${existingSize}/${task.totalBytes} bytes)',
);
task = task.copyWith(
status: DownloadStatus.completed,
filePath: basePath,
bytesDownloaded: existingSize,
);
_updateTask(task);
completer.complete(DownloadResult(task, true));
return;
} else {
_logger.warning(
'Existing file size mismatch for ${task.filename}: '
'expected ${task.totalBytes}, but got $existingSize',
);
await baseFile.delete(); // Remove corrupted file
}
}
// Check existing chunks and calculate progress
final totalChunks = (task.totalBytes / downloadChunkSize).ceil();
final existingChunks =
@@ -169,8 +205,13 @@ class DownloadManager {
'Resuming download for ${task.filename} (${task.bytesDownloaded}/${task.totalBytes} bytes)',
);
for (int i = 0; i < totalChunks; i++) {
if (existingChunks[i] || cancelToken.isCancelled) continue;
_logger.info('Downloading chunk ${i + 1} of $totalChunks');
if (existingChunks[i]) {
continue;
}
if (cancelToken.isCancelled) {
_logger.info('Download cancelled for ${task.filename}');
break;
}
await _downloadChunk(task, basePath, i, totalChunks, cancelToken);
existingChunks[i] = true;
}
@@ -235,7 +276,7 @@ class DownloadManager {
'but got $actualSize bytes',
);
existingChunks[i] = false;
await chunkFile.delete(); // Remove corrupted chunk
// await chunkFile.delete(); // Remove corrupted chunk
}
}
@@ -270,7 +311,7 @@ class DownloadManager {
final endByte = chunkIndex == totalChunks - 1
? task.totalBytes - 1
: (startByte + downloadChunkSize) - 1;
_logger.info('Downloading chunk ${chunkIndex + 1}/$totalChunks');
await _dio.download(
FileUrl.getUrl(task.id, FileUrlType.directDownload),
chunkPath,