upload to temporary name to both identify incomplete uploads and avoid overwriting existing file until completed

Massimo Melina committed Jan 22, 2023 at 09:08 UTC 07c61feb0ae3cbc3a8a9034bf777d6ab7e35c04a
1 file changed +12 -4
src/middlewares.ts
+12 -4
@@ -27,7 +27,7 @@ import basicAuth from 'basic-auth'
27 import { SRPClientSession, SRPParameters, SRPRoutines } from 'tssrp6a'
28 import { srpStep1 } from './api.auth'
29 import { basename, dirname, join } from 'path'
30 -import { createWriteStream, mkdirSync } from 'fs'
30 +import { createWriteStream, mkdirSync, rename } from 'fs'
31 import { pipeline } from 'stream/promises'
32 import formidable from 'formidable'
33 import { notifyClient } from './frontEndApis'
@@ -139,9 +139,17 @@ export const serveGuiAndSharedFiles: Koa.Middleware = async (ctx, next) => {
139 notifyClient(ctx, 'upload.status', { [path]: ctx.status }) // allow browsers to detect failure while still sending body
140 return
141 }
142 - path = join(base.source, path)
143 - mkdirSync(dirname(path), { recursive: true })
144 - return createWriteStream(path)
142 + const fullPath = join(base.source, path)
143 + const dir = dirname(fullPath)
144 + mkdirSync(dir, { recursive: true })
145 + const tempName = join(dir, 'hfs$uploading-' + basename(fullPath).slice(-20))
146 + const ret = createWriteStream(tempName)
147 + ret.on('close', () => {
148 + if (ctx.req.aborted) return
149 + rename(tempName, fullPath, err =>
150 + err && console.error("couldn't rename temp to", fullPath, String(err)))
151 + })
152 + return ret
153 }
154
155 }