Add local vs R2 destination picker for admin asset uploads; v2.0.39
Publish Container / docker (push) Successful in 14m12s

Upload dropdown lets you choose R2 folder (uploads/images/guides/finished)
or local server disk. Asset table shows location column for each file.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
nmemmertandClaude Sonnet 4.6 committed 2026-09-18 12:20:21 -04:00
1 parent 4e6449f3a7
commit c79589b311
3 files changed
+35 -8

No files matched your search

+8 -6
View File
@@ -37,10 +37,12 @@ export function register(app) {
const filename = typeof req.body?.filename === 'string' ? req.body.filename : ''
const dataUrl = typeof req.body?.dataUrl === 'string' ? req.body.dataUrl : ''
const rawFolder = typeof req.body?.folder === 'string' ? req.body.folder : 'uploads'
const rawStorage = typeof req.body?.storage === 'string' ? req.body.storage : 'r2'
const ext = inferImageExtensionFromDataUrl(dataUrl)
const ALLOWED_FOLDERS = ['uploads', 'images', 'guides', 'finished']
const folder = ALLOWED_FOLDERS.includes(rawFolder) ? rawFolder : 'uploads'
const useLocal = rawStorage === 'local' || !isR2Configured()
if (!ext) {
res.status(400).json({ message: 'Upload must be a PNG, JPG, WEBP, GIF, PDF, DOC, or DOCX data URL.' })
@@ -58,20 +60,20 @@ export function register(app) {
const finalName = `${baseName}-${Date.now()}${ext}`
let url
if (isR2Configured()) {
const contentType = dataUrl.match(/^data:([^;]+);base64,/)?.[1] ?? 'application/octet-stream'
url = await uploadToR2(buffer, `${folder}/${finalName}`, contentType)
} else {
if (useLocal) {
await mkdir(UPLOADS_DIR, { recursive: true })
await writeFile(path.join(UPLOADS_DIR, finalName), buffer)
url = `/uploads/${finalName}`
} else {
const contentType = dataUrl.match(/^data:([^;]+);base64,/)?.[1] ?? 'application/octet-stream'
url = await uploadToR2(buffer, `${folder}/${finalName}`, contentType)
}
const metadata = await readUploadsMetadata()
metadata[finalName] = { tags: [], url, folder }
metadata[finalName] = { tags: [], url, folder: useLocal ? 'local' : folder }
await writeUploadsMetadata(metadata)
res.json({ ok: true, asset: { filename: finalName, url, folder } })
res.json({ ok: true, asset: { filename: finalName, url, folder: useLocal ? 'local' : folder, storage: useLocal ? 'local' : 'r2' } })
} catch (err) {
console.error('[admin-assets] upload failed:', err)
res.status(500).json({ message: 'Upload failed.' })