feat(media): infer MIME from extension for empty-type uploads (.md, .html)
Browsers report an empty file.type for files with no OS-registered MIME (esp. .md), which then went up as application/octet-stream and got rejected. Infer the type from the extension for the text types IIOS allows (md/markdown/html/ htm/txt/csv) so those attachments upload. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+14
-1
@@ -14,12 +14,25 @@ export function isImage(mime?: string | null): boolean {
|
|||||||
return !!mime && mime.startsWith("image/");
|
return !!mime && mime.startsWith("image/");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Some types (notably .md) have no OS-registered MIME, so the browser reports an empty file.type.
|
||||||
|
// Fall back to the extension for the text types IIOS allows, else a generic binary.
|
||||||
|
const EXT_MIME: Record<string, string> = {
|
||||||
|
md: "text/markdown", markdown: "text/markdown",
|
||||||
|
html: "text/html", htm: "text/html",
|
||||||
|
txt: "text/plain", csv: "text/csv",
|
||||||
|
};
|
||||||
|
function mimeForFile(file: File): string {
|
||||||
|
if (file.type) return file.type;
|
||||||
|
const ext = file.name.toLowerCase().split(".").pop() ?? "";
|
||||||
|
return EXT_MIME[ext] ?? "application/octet-stream";
|
||||||
|
}
|
||||||
|
|
||||||
/** Upload a File → { contentRef, mimeType, sizeBytes, filename }. Throws on oversize / failure. */
|
/** Upload a File → { contentRef, mimeType, sizeBytes, filename }. Throws on oversize / failure. */
|
||||||
export function useUploadAttachment() {
|
export function useUploadAttachment() {
|
||||||
const { sdk } = useAppShell();
|
const { sdk } = useAppShell();
|
||||||
return useCallback(async (file: File): Promise<UploadedAttachment> => {
|
return useCallback(async (file: File): Promise<UploadedAttachment> => {
|
||||||
if (file.size > MAX_ATTACHMENT_BYTES) throw new Error("File is too large (max 25 MB).");
|
if (file.size > MAX_ATTACHMENT_BYTES) throw new Error("File is too large (max 25 MB).");
|
||||||
const mime = file.type || "application/octet-stream";
|
const mime = mimeForFile(file);
|
||||||
const { objectKey, uploadUrl } = (await sdk.command("crm.media.presignUpload", { mime, sizeBytes: file.size })) as { objectKey: string; uploadUrl: string };
|
const { objectKey, uploadUrl } = (await sdk.command("crm.media.presignUpload", { mime, sizeBytes: file.size })) as { objectKey: string; uploadUrl: string };
|
||||||
const res = await fetch(uploadUrl, { method: "PUT", body: file });
|
const res = await fetch(uploadUrl, { method: "PUT", body: file });
|
||||||
if (!res.ok) throw new Error(`Upload failed (${res.status}).`);
|
if (!res.ok) throw new Error(`Upload failed (${res.status}).`);
|
||||||
|
|||||||
Reference in New Issue
Block a user