Handle incorrect pause
This commit is contained in:
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user