Strip metadata in the ExifTool worker during upload preview.

Cache stripped blobs, show original vs stripped metadata tabs, and keep user-facing errors on fixed store messages with console logging for diagnostics.
This commit is contained in:
2026-10-18 18:02:49 +02:00
parent 18597f4127
commit 1826cef8fe
11 changed files with 305 additions and 32 deletions
+80 -3
View File
@@ -1,9 +1,10 @@
import zeroperlWasmUrl from '@6over3/zeroperl-ts/zeroperl.wasm?url';
import { parseMetadata } from '@uswriting/exiftool';
import { parseMetadata, writeMetadata } from '@uswriting/exiftool';
import { EXIFTOOL_WORKER_INIT_JPEG } from '@/consts/exiftoolWorkerInitJpeg';
import type { ExiftoolWorkerInMessage } from '@/types/workers/exiftoolWorkerInMessage';
import type { ExiftoolWorkerJob } from '@/types/workers/exiftoolWorkerJob';
import { resolveErrorMessage } from '@/utils/resolveErrorMessage';
import { toArrayBuffer } from '@/utils/toArrayBuffer';
/** Custom fetch function for `@uswriting/exiftool` to load `zeroperl.wasm` from the worker. */
const exiftoolParseOptions = { fetch: () => fetch(zeroperlWasmUrl) };
@@ -107,17 +108,87 @@ const processJob = async (job: ExiftoolWorkerJob): Promise<void> => {
const result = await parseMetadata(job.file, exiftoolParseOptions);
if (!result.success) {
self.postMessage({ type: 'read-metadata-error', id: job.id, message: result.error });
const message = result.error ?? 'Could not load image metadata';
console.error('[exiftool-worker] read failed', { id: job.id, file: job.file.name, message });
self.postMessage({ type: 'read-metadata-error', id: job.id, message });
return;
}
self.postMessage({ type: 'read-metadata-done', id: job.id, output: result.data });
} catch (error) {
const message = resolveErrorMessage(error, 'Could not load image metadata');
console.error('[exiftool-worker] read threw', { id: job.id, file: job.file.name, error });
self.postMessage({
type: 'read-metadata-error',
id: job.id,
message: resolveErrorMessage(error, 'Could not load image metadata')
message
});
}
return;
}
if (job.type === 'strip-metadata') {
try {
await initializeWorker();
const result = await writeMetadata(
job.file,
{},
{ args: ['-all='], ...exiftoolParseOptions }
);
if (!result.success) {
const message = result.error ?? 'Could not strip image metadata';
console.error('[exiftool-worker] strip failed', {
id: job.id,
file: job.file.name,
type: job.file.type,
exitCode: result.exitCode,
message
});
self.postMessage({
type: 'strip-metadata-error',
id: job.id,
message
});
return;
}
const data = toArrayBuffer(result.data);
if (!data) {
const message = 'Strip succeeded but returned no image bytes';
console.error('[exiftool-worker] strip missing data', {
id: job.id,
file: job.file.name,
dataType: result.data === null ? 'null' : typeof result.data
});
self.postMessage({ type: 'strip-metadata-error', id: job.id, message });
return;
}
self.postMessage({ type: 'strip-metadata-done', id: job.id, data }, { transfer: [data] });
} catch (error) {
const message = resolveErrorMessage(error, 'Failed to strip metadata');
console.error('[exiftool-worker] strip failed', { id: job.id, file: job.file.name, error });
self.postMessage({
type: 'strip-metadata-error',
id: job.id,
message
});
}
}
@@ -134,5 +205,11 @@ self.addEventListener('message', (event: MessageEvent<ExiftoolWorkerInMessage>)
if (message.type === 'read-metadata') {
enqueue({ type: 'read-metadata', id: message.id, file: message.file });
return;
}
if (message.type === 'strip-metadata') {
enqueue({ type: 'strip-metadata', id: message.id, file: message.file });
}
});