Fix image uploads using the wrong format (#2380)
* fix(app): preserve image attachment MIME types Image intake discarded clipboard and desktop path metadata, then guessed JPEG when a later file object had no type. Resolve MIME once at the platform boundary and require it downstream. * fix(app): honor native picker MIME metadata
This commit is contained in:
@@ -92,7 +92,7 @@ describe("collectImageFilesFromClipboardData", () => {
|
||||
],
|
||||
});
|
||||
|
||||
expect(files).toEqual([imagePng]);
|
||||
expect(files).toEqual([{ file: imagePng, mimeType: "image/png" }]);
|
||||
});
|
||||
|
||||
it("ignores SVG clipboard files", () => {
|
||||
@@ -127,7 +127,10 @@ describe("filesToImageAttachments", () => {
|
||||
type: "",
|
||||
});
|
||||
|
||||
const attachments = await filesToImageAttachments([pngFile, typeLessFile]);
|
||||
const attachments = await filesToImageAttachments([
|
||||
{ file: pngFile, mimeType: "image/png" },
|
||||
{ file: typeLessFile, mimeType: "image/png" },
|
||||
]);
|
||||
|
||||
expect(attachments).toEqual([
|
||||
{
|
||||
@@ -141,7 +144,7 @@ describe("filesToImageAttachments", () => {
|
||||
},
|
||||
{
|
||||
id: "att-2",
|
||||
mimeType: "image/jpeg",
|
||||
mimeType: "image/png",
|
||||
storageType: "web-indexeddb",
|
||||
storageKey: "att-2",
|
||||
fileName: "second",
|
||||
@@ -156,7 +159,7 @@ describe("filesToImageAttachments", () => {
|
||||
type: "image/png",
|
||||
});
|
||||
|
||||
const [attachment] = await filesToImageAttachments([large]);
|
||||
const [attachment] = await filesToImageAttachments([{ file: large, mimeType: "image/png" }]);
|
||||
|
||||
expect(attachment?.storageType).toBe("web-indexeddb");
|
||||
expect(attachment?.byteSize).toBe(4 * 1024 * 1024);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { AttachmentMetadata } from "@/attachments/types";
|
||||
import { persistAttachmentFromBlob } from "@/attachments/service";
|
||||
import { isRasterImageMimeType } from "@/attachments/file-types";
|
||||
import { resolveRasterImageMimeType } from "@/attachments/file-types";
|
||||
|
||||
export interface ClipboardItemLike {
|
||||
kind?: string;
|
||||
@@ -14,40 +14,46 @@ export interface ClipboardDataLike {
|
||||
|
||||
export type ImageAttachmentFromFile = AttachmentMetadata;
|
||||
|
||||
export interface ClipboardImageFile {
|
||||
file: File;
|
||||
mimeType: string;
|
||||
}
|
||||
|
||||
export function collectImageFilesFromClipboardData(
|
||||
clipboardData?: ClipboardDataLike | null,
|
||||
): File[] {
|
||||
): ClipboardImageFile[] {
|
||||
if (!clipboardData?.items) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const files: File[] = [];
|
||||
const files: ClipboardImageFile[] = [];
|
||||
for (const item of Array.from(clipboardData.items)) {
|
||||
if (item?.kind !== "file") {
|
||||
continue;
|
||||
}
|
||||
if (!isRasterImageMimeType(item.type)) {
|
||||
const mimeType = resolveRasterImageMimeType({ mimeType: item.type });
|
||||
if (!mimeType) {
|
||||
continue;
|
||||
}
|
||||
const file = item.getAsFile?.();
|
||||
if (!file) {
|
||||
continue;
|
||||
}
|
||||
files.push(file);
|
||||
files.push({ file, mimeType });
|
||||
}
|
||||
|
||||
return files;
|
||||
}
|
||||
|
||||
export async function filesToImageAttachments(
|
||||
files: readonly File[],
|
||||
files: readonly ClipboardImageFile[],
|
||||
): Promise<ImageAttachmentFromFile[]> {
|
||||
const attachments = await Promise.all(
|
||||
files.map(async (file) => {
|
||||
files.map(async ({ file, mimeType }) => {
|
||||
try {
|
||||
return await persistAttachmentFromBlob({
|
||||
blob: file,
|
||||
mimeType: file.type || "image/jpeg",
|
||||
mimeType,
|
||||
fileName: file.name,
|
||||
});
|
||||
} catch (error) {
|
||||
|
||||
Reference in New Issue
Block a user