From 7e574719f8083b03b48b6bb9343011ee47aef6b3 Mon Sep 17 00:00:00 2001 From: June Date: Fri, 30 Jan 2026 14:18:39 +1300 Subject: [PATCH] Port image routes --- src/routes/api/image/+server.ts | 37 ++++++++++++++++++++++++++++ src/routes/api/image/[id]/+server.ts | 35 ++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 src/routes/api/image/+server.ts create mode 100644 src/routes/api/image/[id]/+server.ts diff --git a/src/routes/api/image/+server.ts b/src/routes/api/image/+server.ts new file mode 100644 index 0000000..8982048 --- /dev/null +++ b/src/routes/api/image/+server.ts @@ -0,0 +1,37 @@ +import { UPLOAD_DIR } from '$env/static/private' +import { promises as fs } from "fs" +import { join } from 'path' +import { randomBytes } from 'crypto'; +import { httpResponse } from '$lib/server/http'; + +export async function POST({ request }) { + try { + const formData = await request.formData(); + const file = formData.get('image'); + + return await writeImage(file as File) + + } catch (error) { + return httpResponse({ error: `Failed to upload image, ${error}` }, 500); + } +} + +async function writeImage(file: File) { + if (!file || !(file instanceof File)) { + return httpResponse({ error: 'No image provided' }, 400); + } + + if (!file.type.match(/^image\/(jpeg|jpg|png)$/)) { + return httpResponse({ error: 'Only JPG and PNG allowed' }, 400); + } + + const ext = file.name.split('.').pop(); + const filename = `${randomBytes(16).toString('hex')}.${ext}`; + const filepath = join(UPLOAD_DIR, filename); + + // Save file + const buffer = Buffer.from(await file.arrayBuffer()); + await fs.writeFile(filepath, buffer); + + return httpResponse({ url: `/api/image/${filename}`}, 201); +} \ No newline at end of file diff --git a/src/routes/api/image/[id]/+server.ts b/src/routes/api/image/[id]/+server.ts new file mode 100644 index 0000000..854891b --- /dev/null +++ b/src/routes/api/image/[id]/+server.ts @@ -0,0 +1,35 @@ +import { UPLOAD_DIR } from '$env/static/private' +import { promises as fs } from "fs" +import { join } from 'path' +import { httpResponse } from '$lib/server/http'; + +export async function GET({ params }) { + try { + const { id } = params + return readImage(id!) + } catch (error) { + return httpResponse({ error: `Failed to retrieve image: ${error}` }, 500); + } +} + +async function readImage(id: string) { + + const filepath = join(UPLOAD_DIR, id); + + try { + await fs.access(filepath); + } catch { + return httpResponse({ error: 'Image not found' }, 404); + } + + const image = await fs.readFile(filepath); + const ext = id.split('.').pop()?.toLowerCase(); + const contentType = ext === 'png' ? 'image/png' : 'image/jpeg'; + + return new Response(image, { + status: 200, + headers: { + 'Content-Type': contentType, + } + }); +} \ No newline at end of file