Files
makelore/src/lib/coding-attachments.ts

46 lines
1.4 KiB
TypeScript

import { hostApiFetch, hostApiFetchBytes } from './host-api';
export const CODING_ATTACHMENT_MAX_BYTES = 16 * 1024 * 1024;
export const CODING_ATTACHMENT_MAX_COUNT = 16;
export const CODING_ATTACHMENT_UPLOAD_CONCURRENCY = 4;
export const CODING_ATTACHMENT_MIMES = new Set([
'image/png',
'image/jpeg',
'image/webp',
'image/gif',
]);
export interface CodingAttachmentRef {
attachmentId: string;
mime: string;
byteLength: number;
}
export async function uploadCodingAttachment(file: File): Promise<CodingAttachmentRef> {
const mime = file.type.trim().toLowerCase();
if (!CODING_ATTACHMENT_MIMES.has(mime)) throw new Error('仅支持 PNG、JPEG、WebP 或 GIF 图片。');
if (file.size <= 0 || file.size > CODING_ATTACHMENT_MAX_BYTES) {
throw new Error('图片不能超过 16 MB。');
}
return await hostApiFetch<CodingAttachmentRef>(
'/api/coding/attachments',
{
method: 'POST',
headers: { 'Content-Type': mime },
body: await file.arrayBuffer(),
},
);
}
export async function loadCodingAttachmentPreview(
attachmentId: string,
): Promise<{ bytes: Uint8Array; mime: string }> {
const response = await hostApiFetchBytes(
`/api/coding/attachments/${encodeURIComponent(attachmentId)}/content`,
);
if (!CODING_ATTACHMENT_MIMES.has(response.contentType)) {
throw new Error('图片附件格式无效。');
}
return { bytes: response.bytes, mime: response.contentType };
}