fix: upload: resume of renamed files didn't work

Massimo Melina committed May 25, 2025 at 14:56 UTC 9509a7d172c0129057fa0b13cbddc8d9d3311d9f
3 files changed +7 -9
frontend/src/misc.ts
+2 -2
@@ -64,9 +64,9 @@ export function hfsEvent(name: string, params?:Dict) {
64 })
65 }
66
67 -export function onHfsEvent(name: string, cb: (params:any, extra: { output: any[], setOrder: Callback<number>, preventDefault: Callback }, output: any[]) => any) {
67 +export function onHfsEvent(name: string, cb: (params:any, extra: { output: any[], setOrder: Callback<number>, preventDefault: Callback }, output: any[]) => any, options?: { once?: boolean }) {
68 const key = 'hfs.' + name
69 - document.addEventListener(key, wrapper)
69 + document.addEventListener(key, wrapper, options)
70 return () => document.removeEventListener(key, wrapper)
71
72 function wrapper(ev: Event) {
frontend/src/uploadQueue.ts
+2 -3
@@ -192,8 +192,7 @@ export async function startUpload(toUpload: ToUpload, to: string, startingResume
192 return hfsEvent(PREFIX + data.path, data.hash)
193 if (name === UPLOAD_RESUMABLE) {
194 waitSecondChunk.resolve()
195 - const path = getFilePath(uploading.file)
196 - if (path !== data.path) return // is it about current file?
195 + if (uploading.name !== data.path) return // is it about current file?
196 if (data.written)
197 return lastWrittenReceived = data.written
198 const {size} = data //TODO use toUpload?
@@ -208,7 +207,7 @@ export async function startUpload(toUpload: ToUpload, to: string, startingResume
207 console.debug('upload unchanged')
208 }
209 else { // timestamp may miss if the file is left by old version, or HFS was killed
211 - const hashFromServer = new Promise<any>(res => onHfsEvent(PREFIX + path, res))
210 + const hashFromServer = new Promise<any>(res => onHfsEvent(PREFIX + getFilePath(uploading.file), res, { once: true }))
211 const hashed = await calcHash(uploading.file, size) // therefore, we attempt a check using the hash
212 if (!hashed) return // too late, we are working on another file
213 if (hashed !== await hashFromServer) return console.debug('upload hash mismatch')
src/upload.ts
+3 -4
@@ -166,7 +166,6 @@ export function uploadWriter(base: VfsNode, baseUri: string, path: string, ctx:
166 tempName = resumableTempName
167 }
168 let isWritingSecondFile = tempName === altTempName
169 - cancelDeletion(tempName)
169 const fullSize = stillToWrite + resume
170 ctx.state.uploadDestinationPath = tempName
171 // allow plugins to mess with the write-stream, because the read-stream can be complicated in case of multipart
@@ -183,6 +182,7 @@ export function uploadWriter(base: VfsNode, baseUri: string, path: string, ctx:
182 writeStream.pipe(fileStream)
183 Object.assign(obj, { fileStream })
184 trackProgress()
185 + cancelDeletion(tempName)
186 uploadingFiles.set(fullPath, ctx)
187 console.debug('upload started')
188 // the file stream doesn't have an event for data being written, so we use 'data' of its feeder, which happens before, so we postpone a bit, trying to have a fresher number
@@ -274,9 +274,8 @@ export function uploadWriter(base: VfsNode, baseUri: string, path: string, ctx:
274 }
275
276 function checkIfNewUploadBecameLargerThanResumable() {
277 - if (!isWritingSecondFile)
278 - return sendCurrentSize() // keep the client updated in case it needs to resume on disconnection
279 - if (getCurrentSize() > firstResumableStats?.size!)
277 + sendCurrentSize() // keep the client updated in case it needs to resume on disconnection
278 + if (isWritingSecondFile && getCurrentSize() > firstResumableStats?.size!)
279 try { // better be sync here, as we don't want the upload to finish in the middle of the rename
280 fs.renameSync(tempName, firstTempName) // try to rename $upload2 to $upload, overwriting
281 tempName = firstTempName