Fix Invalid PDF structure after reload for uploaded documents.
Stop inventing /fixtures/pdfs/<title> URLs when blob bytes are missing; rely on IndexedDB-hydrated byte store. Seeded tests set an explicit fixture uri. Session metadata already survived; PDF bytes now survive too.
This commit is contained in:
parent
9dbe806487
commit
a73d45bfac
3 changed files with 26 additions and 8 deletions
|
|
@ -38,11 +38,16 @@ describe("resolvePdfViewerUrl", () => {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("falls back to fixture path when only a stale blob uri is stored", () => {
|
it("returns null for stale blob uri without live bytes (no fixture guess)", () => {
|
||||||
const store = createPdfByteStore();
|
const store = createPdfByteStore();
|
||||||
expect(
|
expect(
|
||||||
resolvePdfViewerUrl(doc({ uri: "blob:revoked", title: "a.pdf" }), store),
|
resolvePdfViewerUrl(doc({ uri: "blob:revoked", title: "a.pdf" }), store),
|
||||||
).toBe("/fixtures/pdfs/a.pdf");
|
).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns null when uri was stripped on persist and bytes are gone", () => {
|
||||||
|
const store = createPdfByteStore();
|
||||||
|
expect(resolvePdfViewerUrl(doc({ uri: undefined, title: "upload.pdf" }), store)).toBeNull();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -51,4 +56,4 @@ describe("isEphemeralBlobUri", () => {
|
||||||
expect(isEphemeralBlobUri("blob:http://localhost/x")).toBe(true);
|
expect(isEphemeralBlobUri("blob:http://localhost/x")).toBe(true);
|
||||||
expect(isEphemeralBlobUri("/fixtures/pdfs/x.pdf")).toBe(false);
|
expect(isEphemeralBlobUri("/fixtures/pdfs/x.pdf")).toBe(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,10 @@
|
||||||
* Uploaded PDFs are served via ephemeral `blob:` URLs owned by
|
* Uploaded PDFs are served via ephemeral `blob:` URLs owned by
|
||||||
* `PdfByteStore`. Those URLs must not be persisted (see persistence
|
* `PdfByteStore`. Those URLs must not be persisted (see persistence
|
||||||
* sanitization) and must be re-resolved from live bytes on every render.
|
* sanitization) and must be re-resolved from live bytes on every render.
|
||||||
|
*
|
||||||
|
* After a reload, bytes come back via IndexedDB hydrate into the byte store.
|
||||||
|
* Never invent a `/fixtures/pdfs/<title>` URL for arbitrary uploads — that
|
||||||
|
* path 404s (or returns HTML) and PDF.js reports "Invalid PDF structure".
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { Document } from "@shared/document";
|
import type { Document } from "@shared/document";
|
||||||
|
|
@ -20,7 +24,8 @@ export function isEphemeralBlobUri(uri: string | undefined): boolean {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prefer the byte store's live blob URL for uploaded documents; fall back
|
* Prefer the byte store's live blob URL for uploaded documents; fall back
|
||||||
* to a stable HTTP fixture path or a non-blob `document.uri`.
|
* to a stable non-blob `document.uri` (e.g. fixture HTTP path). Returns
|
||||||
|
* `null` when bytes are not available — ViewerShell shows re-upload copy.
|
||||||
*/
|
*/
|
||||||
export function resolvePdfViewerUrl(
|
export function resolvePdfViewerUrl(
|
||||||
document: Document,
|
document: Document,
|
||||||
|
|
@ -33,8 +38,8 @@ export function resolvePdfViewerUrl(
|
||||||
return document.uri;
|
return document.uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
const titleOrId = document.title ?? document.id;
|
// Stale blob URI and no in-memory/IDB bytes: do not guess a fixture path.
|
||||||
return `/fixtures/pdfs/${encodeURIComponent(titleOrId)}`;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** True when bytes exist in the store but the document record lacks a URI. */
|
/** True when bytes exist in the store but the document record lacks a URI. */
|
||||||
|
|
@ -43,4 +48,4 @@ export function documentHasUploadedBytes(
|
||||||
byteStore: PdfByteStore,
|
byteStore: PdfByteStore,
|
||||||
): boolean {
|
): boolean {
|
||||||
return byteStore.has(documentId);
|
return byteStore.has(documentId);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -49,10 +49,18 @@ export function seedSessionWithDoc(opts: SeedOptions): SeedResult {
|
||||||
lastOpenedAt: now,
|
lastOpenedAt: now,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Stable HTTP fixture URI so the viewer mounts without IndexedDB bytes.
|
||||||
|
// (resolvePdfViewerUrl no longer invents /fixtures paths from title alone —
|
||||||
|
// that produced "Invalid PDF structure" for arbitrary uploads after reload.)
|
||||||
const document: Document = {
|
const document: Document = {
|
||||||
id: documentId,
|
id: documentId,
|
||||||
mediaType: "application/pdf",
|
mediaType: "application/pdf",
|
||||||
...(opts.documentTitle ? { title: opts.documentTitle } : {}),
|
...(opts.documentTitle
|
||||||
|
? {
|
||||||
|
title: opts.documentTitle,
|
||||||
|
uri: `/fixtures/pdfs/${encodeURIComponent(opts.documentTitle)}`,
|
||||||
|
}
|
||||||
|
: {}),
|
||||||
fingerprint: "seed-fingerprint",
|
fingerprint: "seed-fingerprint",
|
||||||
createdAt: now,
|
createdAt: now,
|
||||||
updatedAt: now,
|
updatedAt: now,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue