Fix image upload 500 in production: use UPLOAD_DIR env for absolute path
Deploy to LXC / deploy (push) Successful in 20s

In production with adapter-node, the relative path 'static/uploads'
doesn't resolve correctly. Now uses UPLOAD_DIR env variable (absolute
path) for both saving and serving uploaded files.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-09 14:08:00 +07:00
parent 6cd5f28bf7
commit 50689c46e5
2 changed files with 10 additions and 6 deletions
+6 -4
View File
@@ -1,9 +1,10 @@
import { randomUUID } from 'crypto';
import { writeFile, unlink, mkdir } from 'fs/promises';
import { join, extname } from 'path';
import { join, extname, resolve } from 'path';
import sharp from 'sharp';
import { env } from '$env/dynamic/private';
const UPLOAD_BASE = 'static/uploads';
const UPLOAD_BASE = resolve(env.UPLOAD_DIR || 'static/uploads');
const THUMBNAIL_WIDTH = 300;
const ALLOWED_IMAGE_TYPES = [
@@ -67,8 +68,9 @@ export async function saveDocument(file: File): Promise<{ filePath: string; orig
export async function deleteFile(filePath: string): Promise<void> {
try {
// filePath is like /uploads/devices/xxx.jpg, need to prepend static/
const fullPath = join('static', filePath);
// filePath is like /uploads/devices/xxx.jpg — strip /uploads/ prefix and join with UPLOAD_BASE
const relativePath = filePath.replace(/^\/uploads\//, '');
const fullPath = join(UPLOAD_BASE, relativePath);
await unlink(fullPath);
} catch {
// File may already be deleted
+4 -2
View File
@@ -1,7 +1,8 @@
import type { RequestHandler } from './$types';
import { readFile } from 'fs/promises';
import { join, extname } from 'path';
import { join, extname, resolve } from 'path';
import { error } from '@sveltejs/kit';
import { env } from '$env/dynamic/private';
const MIME_TYPES: Record<string, string> = {
'.jpg': 'image/jpeg',
@@ -21,7 +22,8 @@ export const GET: RequestHandler = async ({ params }) => {
// Prevent directory traversal
if (filePath.includes('..')) error(400, 'Invalid path');
const fullPath = join('static', 'uploads', filePath);
const uploadBase = resolve(env.UPLOAD_DIR || 'static/uploads');
const fullPath = join(uploadBase, filePath);
try {
const data = await readFile(fullPath);