Fix premature hybrid extraction of incomplete archive parts
Item-Recovery incorrectly marked partially downloaded files as "completed" when the file size was >= 50% of expected size. A 627 MB partial download of a 1001 MB file (62.7%) would pass the check and trigger hybrid extraction on incomplete RAR archives. Fix: require file to be within one allocation unit (4 KB) of the expected size instead of 50%. Also add a pre-allocation guard: if the file appears to be at the expected size but downloadedBytes is significantly behind (< 95%), skip recovery (likely a pre-allocated sparse file from a crash). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
99074464fb
commit
0f2823bdc2
@ -7365,10 +7365,11 @@ export class DownloadManager extends EventEmitter {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const stat = await fs.promises.stat(item.targetPath);
|
const stat = await fs.promises.stat(item.targetPath);
|
||||||
// Require file to be either ≥50% of expected size or at least 10 KB to avoid
|
// Require file to be essentially complete — within one allocation unit of the
|
||||||
// recovering tiny error-response files (e.g. 9-byte "Forbidden" pages).
|
// expected size. The old 50% threshold incorrectly recovered partial downloads
|
||||||
|
// (e.g. 627 MB of 1001 MB) and triggered hybrid extraction on incomplete archives.
|
||||||
const minSize = item.totalBytes && item.totalBytes > 0
|
const minSize = item.totalBytes && item.totalBytes > 0
|
||||||
? Math.max(10240, Math.floor(item.totalBytes * 0.5))
|
? Math.max(10240, item.totalBytes - ALLOCATION_UNIT_SIZE)
|
||||||
: 10240;
|
: 10240;
|
||||||
if (stat.size >= minSize) {
|
if (stat.size >= minSize) {
|
||||||
// Re-check: another task may have started this item during the await
|
// Re-check: another task may have started this item during the await
|
||||||
@ -7376,6 +7377,14 @@ export class DownloadManager extends EventEmitter {
|
|||||||
|| item.status === "validating" || item.status === "integrity_check") {
|
|| item.status === "validating" || item.status === "integrity_check") {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
// Guard against pre-allocated sparse files from a hard crash: file has
|
||||||
|
// the full expected size but downloadedBytes is significantly behind.
|
||||||
|
if (item.downloadedBytes > 0 && item.totalBytes && item.totalBytes > 0
|
||||||
|
&& stat.size >= item.totalBytes - ALLOCATION_UNIT_SIZE
|
||||||
|
&& item.downloadedBytes < item.totalBytes * 0.95) {
|
||||||
|
logger.warn(`Item-Recovery: ${item.fileName} uebersprungen – vermutlich pre-alloc (stat=${humanSize(stat.size)}, bytes=${humanSize(item.downloadedBytes)}, total=${humanSize(item.totalBytes)})`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
logger.info(`Item-Recovery: ${item.fileName} war "${item.status}" aber Datei existiert (${humanSize(stat.size)}), setze auf completed`);
|
logger.info(`Item-Recovery: ${item.fileName} war "${item.status}" aber Datei existiert (${humanSize(stat.size)}), setze auf completed`);
|
||||||
item.status = "completed";
|
item.status = "completed";
|
||||||
item.fullStatus = this.settings.autoExtract ? "Entpacken - Ausstehend" : `Fertig (${humanSize(stat.size)})`;
|
item.fullStatus = this.settings.autoExtract ? "Entpacken - Ausstehend" : `Fertig (${humanSize(stat.size)})`;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user