These docs describe changes that aren’t released yet. For the newest release, see the released docs.
Open someone else's file
You’ll open a PDF from someone else, with a password if it needs one and tighter limits than the defaults, and get the outcome as a value. You need this wherever you accept uploads: a stranger’s file can be damaged, locked or built to use up memory.
The function opens the bytes under its limits and returns the page count and warning codes, or the error’s code and hint:
// Open bytes from someone else: an optional password, tighter limits than the defaults, and the// outcome as a value rather than an exception. The example writes nothing: it returns what it found.import { Document, isLaminaPdfError } from "@laminapdf/sdk";
const MiB = 1024 * 1024;/** Limits for an upload endpoint: each decoded stream, and all of them together. */const LIMITS = { maxStreamDecoded: 16 * MiB, maxDecodedTotal: 64 * MiB } as const;
/** What opening a file gave: its page count and warning codes, or why it didn't open. */export type Opened = | { readonly ok: true; readonly pages: number; readonly warnings: readonly string[] } | { readonly ok: false; readonly code: string; readonly hint: string | undefined };
/** Opens `bytes`, with `password` if the file needs one, under {@link LIMITS}. Needs `init()`. */export function openUntrusted(bytes: Uint8Array, password?: string): Opened { try { using doc = Document.open(bytes, { ...(password === undefined ? {} : { password }), limits: LIMITS }); // Repairs and dropped values are warnings: the file opened, but not exactly as written. return { ok: true, pages: doc.pageCount, warnings: doc.warnings.map((w) => w.code) }; } catch (e) { // `password-required`, `wrong-password`, `not-pdf`, `limit-exceeded`, …: a coded error whose // message and hint never contain text from the file. Anything else is a bug: let it throw. if (isLaminaPdfError(e)) return { ok: false, code: e.code, hint: e.hint }; throw e; }}It writes no PDF. The value it returns is the result: { ok: true, pages, warnings } for a file that opened, or { ok: false, code, hint }, such as password-required for a locked file opened without its password.
How it works
Section titled “How it works”- It needs only
init(): opening a file uses the base module, without fonts or text. Document.opengets the password only when you pass one, and tries it against both of the file’s passwords. See Open password-protected files.LIMITSallows 16 MiB decoded from one stream and 64 MiB in all, against defaults of 64 MiB and 1 GiB. A file that needs more fails withlimit-exceeded, and every other limit keeps its default.- A file can open and still carry warnings: each one names a repair or a dropped value, and the function returns their codes.
isLaminaPdfError(e)picks out Lamina PDF’s coded errors, whose message and hint never contain text from the file. Any other error is a bug, so the function throws it again.usingfrees the document as soon as the function returns, so the WebAssembly side keeps no copy of the file.
What to change
Section titled “What to change”- Ask for the password again: on
password-requiredorwrong-password, ask your user and callopenUntrustedagain with their answer. - Name the limit: on
limit-exceeded, returne.data?.limittoo. It names the limit the file went over as Rust spells it, such asmax_stream_decodedformaxStreamDecoded. - Other limits: add any limit from the table in Open files you don’t trust, such as a lower
maxNestingDepth. - Refuse damaged files: add
strict: trueto the options, and a file that needs repair fails withstrictinstead of opening with warnings.
Next: save in a Web Worker, so a large file never freezes the page.