You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
46 lines
1.2 KiB
46 lines
1.2 KiB
'use server';
|
|
|
|
import { uploadBuffer } from '@/lib/ftps';
|
|
|
|
const MIME_EXT: Record<string, string> = {
|
|
'image/png': '.png',
|
|
'image/jpeg': '.jpg',
|
|
'image/webp': '.webp',
|
|
};
|
|
|
|
export interface UploadResult {
|
|
ok: boolean;
|
|
url?: string;
|
|
error?: string;
|
|
}
|
|
|
|
/**
|
|
* Receives a captured result image and uploads it to the customer FTPS server.
|
|
* Invoked from the client (ResultStep) via an event handler, not a form.
|
|
*
|
|
* Runs on the Node.js runtime (standalone server) — required by `basic-ftp`.
|
|
*/
|
|
export async function uploadResultImage(
|
|
formData: FormData,
|
|
): Promise<UploadResult> {
|
|
try {
|
|
const image = formData.get('image');
|
|
if (!(image instanceof File)) {
|
|
return { ok: false, error: 'missing image' };
|
|
}
|
|
|
|
const ext = MIME_EXT[image.type] ?? '.png';
|
|
const buffer = Buffer.from(await image.arrayBuffer());
|
|
const url = await uploadBuffer(buffer, ext);
|
|
|
|
// TODO: HEAD-verify the public URL is reachable before returning, so the QR
|
|
// never points at a not-yet-served file (architecture.md §5.1).
|
|
|
|
return { ok: true, url };
|
|
} catch (err) {
|
|
return {
|
|
ok: false,
|
|
error: err instanceof Error ? err.message : 'upload failed',
|
|
};
|
|
}
|
|
}
|
|
|