mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
feat(api): add multipart file upload, workspace management, and download routes
- Register @fastify/multipart plugin with size limits from env config - Workspace manager: createWorkspace, getWorkspacePath, cleanupWorkspace - File validation: magic byte detection, format check, megapixel limit - POST /api/v1/upload: multipart upload with validation, returns jobId + file metadata - GET /api/v1/download/:jobId/:filename: serve files with Content-Disposition - Path traversal guards on all file-serving endpoints - Add @stirling-image/image-engine and sharp as API dependencies - Add apiUpload, getDownloadUrl, apiDownloadBlob to web client
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
import { mkdir, rm } from "node:fs/promises";
|
||||
import { join } from "node:path";
|
||||
import { env } from "../config.js";
|
||||
|
||||
/**
|
||||
* Create a workspace directory structure for a processing job.
|
||||
* Returns the workspace root path.
|
||||
*/
|
||||
export async function createWorkspace(jobId: string): Promise<string> {
|
||||
const root = getWorkspacePath(jobId);
|
||||
await mkdir(join(root, "input"), { recursive: true });
|
||||
await mkdir(join(root, "output"), { recursive: true });
|
||||
return root;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the workspace root path for a job.
|
||||
*/
|
||||
export function getWorkspacePath(jobId: string): string {
|
||||
return join(env.WORKSPACE_PATH, jobId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the entire workspace directory for a job.
|
||||
*/
|
||||
export async function cleanupWorkspace(jobId: string): Promise<void> {
|
||||
const root = getWorkspacePath(jobId);
|
||||
await rm(root, { recursive: true, force: true });
|
||||
}
|
||||
Reference in New Issue
Block a user