fix: upload: temp file on Windows won't be deleted until hfs is quit #751

Massimo Melina committed Sep 28, 2024 at 13:42 UTC 5d04780dca45678f32770c91fd004c663b984cda
1 file changed +7 -6
src/upload.ts
+7 -6
@@ -6,7 +6,7 @@ import { basename, dirname, extname, join } from 'path'
6 import fs from 'fs'
7 import {
8 Callback, dirTraversal, loadFileAttr, pendingPromise, storeFileAttr, try_,
9 - createStreamLimiter, isWindowsDrive,
9 + createStreamLimiter
10 } from './misc'
11 import { notifyClient } from './frontEndApis'
12 import { defineConfig } from './config'
@@ -17,7 +17,7 @@ import { getCurrentUsername } from './auth'
17 import { setCommentFor } from './comments'
18 import _ from 'lodash'
19 import events from './events'
20 -import { rename } from 'fs/promises'
20 +import { rename, rm } from 'fs/promises'
21
22 export const deleteUnfinishedUploadsAfter = defineConfig<undefined|number>('delete_unfinished_uploads_after', 86_400)
23 export const minAvailableMb = defineConfig('min_available_mb', 100)
@@ -104,7 +104,7 @@ export function uploadWriter(base: VfsNode, path: string, ctx: Koa.Context) {
104 const size = resumable && try_(() => fs.statSync(resumable).size)
105 if (size === undefined) // stat failed
106 return fail(HTTP_SERVER_ERROR)
107 - if (resume > size)
107 + if (_.isNumber(size) && resume > size)
108 return fail(HTTP_RANGE_NOT_SATISFIABLE)
109 // warn frontend about resume possibility
110 let resumableLost = false
@@ -143,9 +143,10 @@ export function uploadWriter(base: VfsNode, path: string, ctx: Koa.Context) {
143 const lockMiddleware = pendingPromise() // outside we need to know when all operations stopped
144 writeStream.once('close', async () => {
145 try {
146 + await new Promise(res => fileStream.close(res)) // this only seem to be necessary on Windows
147 if (ctx.req.aborted) {
148 if (resumable && !resumableLost && !resuming) // we don't want to be left with 2 temp files
148 - return delayedDelete(tempName, 0)
149 + return rm(tempName)
150 const sec = deleteUnfinishedUploadsAfter.get()
151 return _.isNumber(sec) && delayedDelete(tempName, sec)
152 }
@@ -164,8 +165,8 @@ export function uploadWriter(base: VfsNode, path: string, ctx: Koa.Context) {
165 setUploadMeta(dest, ctx)
166 if (ctx.query.comment)
167 void setCommentFor(dest, String(ctx.query.comment))
167 - if (resumable)
168 - delayedDelete(resumable, 0)
168 + if (resumable && !resuming) // this happens if user decided to not resume and the new upload finished before delayedDelete
169 + rm(resumable).catch(console.warn)
170 events.emit('uploadFinished', obj)
171 if (resEvent) for (const cb of resEvent)
172 if (_.isFunction(cb))