admin/config: Don't overwrite uploading https://github.com/rejetto/hfs/issues/110
Massimo Melina committed
Feb 21, 2023 at 00:12 UTC
ced75d837d04f4c22560ba3cb9055c7692a24d7f
2 files changed
+17
-5
admin/src/ConfigPage.ts
+3
-1
@@ -104,7 +104,7 @@ export default function ConfigPage() {
104
...with_(status?.https.error, e => isKeyError(e) ? { error: true, helperText: e } : null)
105
},
106
{ k: 'open_browser_at_start', comp: BoolField },
107
- { k: 'localhost_admin', comp: BoolField, label: "Admin access for localhost connections",
107
+ { k: 'localhost_admin', comp: BoolField, sm: 12, md: 6, label: "Admin access for localhost connections",
108
getError: x => !x && admins?.length===0 && "First create at least one admin account",
109
helperText: "To access Admin without entering credentials"
110
},
@@ -126,6 +126,8 @@ export default function ConfigPage() {
126
helperText: "If time is not enough, the browser will not show download percentage" },
127
{ k: 'favicon', comp: FileField, sm: 6, md: 6, fileMask: '*.png|*.ico|*.jpg|*.jpeg|*.gif|*.svg',
128
helperText: "The icon associated to your website" },
129
+ { k: 'dont_overwrite_uploading', comp: BoolField, md: 4, label: "Don't overwrite uploading",
130
+ helperText: "Files will be numbered to avoid overwriting" },
131
{ k: 'custom_header', multiline: true, sm: 12, md: 6, sx: { '& textarea': { fontFamily: 'monospace' } },
132
helperText: "Any HTML code here will be displayed on top of the Frontend"
133
},
src/upload.ts
+14
-4
@@ -7,7 +7,7 @@ import {
7
HTTP_SERVER_ERROR,
8
HTTP_UNAUTHORIZED
9
} from './const'
10
-import { basename, dirname, join } from 'path'
10
+import { basename, dirname, extname, join } from 'path'
11
import fs from 'fs'
12
import { Callback, try_ } from './misc'
13
import { notifyClient } from './frontEndApis'
@@ -16,6 +16,7 @@ import { getFreeDiskSync } from './util-os'
16
17
export const deleteUnfinishedUploadsAfter = defineConfig('delete_unfinished_uploads_after')
18
export const minAvailableMb = defineConfig('min_available_mb', 100)
19
+const dontOverwriteUploading = defineConfig('dont_overwrite_uploading', false)
20
21
const waitingToBeDeleted: Record<string, ReturnType<typeof setTimeout>> = {}
22
@@ -64,12 +65,21 @@ export function uploadWriter(base: VfsNode, path: string, ctx: Koa.Context) {
65
}
66
cancelDeletion(tempName)
67
ret.on('close', () => {
67
- if (!ctx.req.aborted)
68
- return fs.rename(tempName, fullPath, err => {
69
- err && console.error("couldn't rename temp to", fullPath, String(err))
68
+ if (!ctx.req.aborted) {
69
+ let dest = fullPath
70
+ if (dontOverwriteUploading.get() && fs.existsSync(dest)) {
71
+ const ext = extname(dest)
72
+ const base = dest.slice(0, -ext.length)
73
+ let i = 1
74
+ do dest = `${base} (${i++})${ext}`
75
+ while (fs.existsSync(dest))
76
+ }
77
+ return fs.rename(tempName, dest, err => {
78
+ err && console.error("couldn't rename temp to", dest, String(err))
79
if (resumable)
80
delayedDelete(resumable, 0)
81
})
82
+ }
83
if (resumable) // we don't want to be left with 2 temp files
84
return delayedDelete(tempName, 0)
85
const sec = deleteUnfinishedUploadsAfter.get()