mirror of
https://github.com/ImranR98/Obtainium.git
synced 2025-07-16 14:46:44 +02:00
Attempt to fix "double download" bug (#2073)
This commit is contained in:
@ -151,13 +151,15 @@ Future<File> downloadFileWithRetry(String url, String fileName,
|
|||||||
{bool useExisting = true,
|
{bool useExisting = true,
|
||||||
Map<String, String>? headers,
|
Map<String, String>? headers,
|
||||||
int retries = 3,
|
int retries = 3,
|
||||||
bool allowInsecure = false}) async {
|
bool allowInsecure = false,
|
||||||
|
LogsProvider? logs}) async {
|
||||||
try {
|
try {
|
||||||
return await downloadFile(
|
return await downloadFile(
|
||||||
url, fileName, fileNameHasExt, onProgress, destDir,
|
url, fileName, fileNameHasExt, onProgress, destDir,
|
||||||
useExisting: useExisting,
|
useExisting: useExisting,
|
||||||
headers: headers,
|
headers: headers,
|
||||||
allowInsecure: allowInsecure);
|
allowInsecure: allowInsecure,
|
||||||
|
logs: logs);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (retries > 0 && e is ClientException) {
|
if (retries > 0 && e is ClientException) {
|
||||||
await Future.delayed(const Duration(seconds: 5));
|
await Future.delayed(const Duration(seconds: 5));
|
||||||
@ -166,7 +168,8 @@ Future<File> downloadFileWithRetry(String url, String fileName,
|
|||||||
useExisting: useExisting,
|
useExisting: useExisting,
|
||||||
headers: headers,
|
headers: headers,
|
||||||
retries: (retries - 1),
|
retries: (retries - 1),
|
||||||
allowInsecure: allowInsecure);
|
allowInsecure: allowInsecure,
|
||||||
|
logs: logs);
|
||||||
} else {
|
} else {
|
||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
@ -219,7 +222,8 @@ Future<File> downloadFile(String url, String fileName, bool fileNameHasExt,
|
|||||||
Function? onProgress, String destDir,
|
Function? onProgress, String destDir,
|
||||||
{bool useExisting = true,
|
{bool useExisting = true,
|
||||||
Map<String, String>? headers,
|
Map<String, String>? headers,
|
||||||
bool allowInsecure = false}) async {
|
bool allowInsecure = false,
|
||||||
|
LogsProvider? logs}) async {
|
||||||
// Send the initial request but cancel it as soon as you have the headers
|
// Send the initial request but cancel it as soon as you have the headers
|
||||||
var reqHeaders = headers ?? {};
|
var reqHeaders = headers ?? {};
|
||||||
var req = Request('GET', Uri.parse(url));
|
var req = Request('GET', Uri.parse(url));
|
||||||
@ -280,6 +284,42 @@ Future<File> downloadFile(String url, String fileName, bool fileNameHasExt,
|
|||||||
// Download to a '.temp' file (to distinguish btn. complete/incomplete files)
|
// Download to a '.temp' file (to distinguish btn. complete/incomplete files)
|
||||||
File tempDownloadedFile = File('${downloadedFile.path}.part');
|
File tempDownloadedFile = File('${downloadedFile.path}.part');
|
||||||
|
|
||||||
|
// If there is already a temp file, a download may already be in progress - account for this (see #2073)
|
||||||
|
bool tempFileExists = tempDownloadedFile.existsSync();
|
||||||
|
if (tempFileExists && useExisting) {
|
||||||
|
logs?.add(
|
||||||
|
'Partial download exists - will wait: ${tempDownloadedFile.uri.pathSegments.last}');
|
||||||
|
bool isDownloading = true;
|
||||||
|
int currentTempFileSize = await tempDownloadedFile.length();
|
||||||
|
bool shouldReturn = false;
|
||||||
|
while (isDownloading) {
|
||||||
|
await Future.delayed(Duration(seconds: 7));
|
||||||
|
if (tempDownloadedFile.existsSync()) {
|
||||||
|
int newTempFileSize = await tempDownloadedFile.length();
|
||||||
|
if (newTempFileSize > currentTempFileSize) {
|
||||||
|
currentTempFileSize = newTempFileSize;
|
||||||
|
logs?.add(
|
||||||
|
'Existing partial download still in progress: ${tempDownloadedFile.uri.pathSegments.last}');
|
||||||
|
} else {
|
||||||
|
logs?.add(
|
||||||
|
'Ignoring existing partial download: ${tempDownloadedFile.uri.pathSegments.last}');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
shouldReturn = downloadedFile.existsSync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (shouldReturn) {
|
||||||
|
logs?.add(
|
||||||
|
'Existing partial download completed - not repeating: ${tempDownloadedFile.uri.pathSegments.last}');
|
||||||
|
client.close();
|
||||||
|
return downloadedFile;
|
||||||
|
} else {
|
||||||
|
logs?.add(
|
||||||
|
'Existing partial download not in progress: ${tempDownloadedFile.uri.pathSegments.last}');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If the range feature is not available (or you need to start a ranged req from 0),
|
// If the range feature is not available (or you need to start a ranged req from 0),
|
||||||
// complete the already-started request, else cancel it and start a ranged request,
|
// complete the already-started request, else cancel it and start a ranged request,
|
||||||
// and open the file for writing in the appropriate mode
|
// and open the file for writing in the appropriate mode
|
||||||
@ -419,9 +459,7 @@ class AppsProvider with ChangeNotifier {
|
|||||||
// Delete any partial APKs (if safe to do so)
|
// Delete any partial APKs (if safe to do so)
|
||||||
var cutoff = DateTime.now().subtract(const Duration(days: 7));
|
var cutoff = DateTime.now().subtract(const Duration(days: 7));
|
||||||
APKDir.listSync()
|
APKDir.listSync()
|
||||||
.where((element) =>
|
.where((element) => element.statSync().modified.isBefore(cutoff))
|
||||||
element.path.endsWith('.part') ||
|
|
||||||
element.statSync().modified.isBefore(cutoff))
|
|
||||||
.forEach((partialApk) {
|
.forEach((partialApk) {
|
||||||
if (!areDownloadsRunning()) {
|
if (!areDownloadsRunning()) {
|
||||||
partialApk.delete(recursive: true);
|
partialApk.delete(recursive: true);
|
||||||
@ -495,7 +533,8 @@ class AppsProvider with ChangeNotifier {
|
|||||||
prevProg = prog;
|
prevProg = prog;
|
||||||
}, APKDir.path,
|
}, APKDir.path,
|
||||||
useExisting: useExisting,
|
useExisting: useExisting,
|
||||||
allowInsecure: app.additionalSettings['allowInsecure'] == true);
|
allowInsecure: app.additionalSettings['allowInsecure'] == true,
|
||||||
|
logs: logs);
|
||||||
// Set to 90 for remaining steps, will make null in 'finally'
|
// Set to 90 for remaining steps, will make null in 'finally'
|
||||||
if (apps[app.id] != null) {
|
if (apps[app.id] != null) {
|
||||||
apps[app.id]!.downloadProgress = -1;
|
apps[app.id]!.downloadProgress = -1;
|
||||||
@ -1124,7 +1163,8 @@ class AppsProvider with ChangeNotifier {
|
|||||||
forAPKDownload:
|
forAPKDownload:
|
||||||
fileUrl.key.endsWith('.apk') ? true : false),
|
fileUrl.key.endsWith('.apk') ? true : false),
|
||||||
useExisting: false,
|
useExisting: false,
|
||||||
allowInsecure: app.additionalSettings['allowInsecure'] == true);
|
allowInsecure: app.additionalSettings['allowInsecure'] == true,
|
||||||
|
logs: logs);
|
||||||
notificationsProvider
|
notificationsProvider
|
||||||
.notify(DownloadedNotification(fileUrl.key, fileUrl.value));
|
.notify(DownloadedNotification(fileUrl.key, fileUrl.value));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
Reference in New Issue
Block a user