Opening documents
engine.open() gives you a handle to one document. Everything you do with the document starts
from that handle.
const doc = await engine.open({ kind: 'token', token: () => fetchDocumentToken('contract') });Open a document#
The document is already on your server, so you open it by reference. There are three ways, depending on where the credential comes from:
| Input | When to use it |
|---|---|
{ kind: 'token', token } | Your backend created a token for this user and this document. |
{ kind: 'id', id } | Your app has a token for your whole account (admin tools, jobs). |
{ kind: 'share', shareToken } | A public share link from the CloudPDF dashboard. |
Authentication shows how to create tokens and when to use each.
open() fetches the document’s details from the server, never the file itself. Pages, text and
images arrive as you ask for them.
Password-protected files#
A PDF can have its own password. When you know it, pass it when you open:
const doc = await engine.open(input, { password: 'secret' });When you don’t, open without one and ask the user only if the file needs it.
doc.security.passwordPrompt tells you:
const doc = await engine.open(input);
if (doc.security.passwordPrompt.state === 'required') {
const password = await askUserForPassword();
await doc.security.unlock({ password });
}passwordPrompt.state | What it means |
|---|---|
'none' | Nothing to do: the file has no password, or it’s already fully unlocked. |
'required' | The file can’t be read without its password. Ask before you do anything else. |
'optional' | The file is open, but its owner password would give more rights. You may offer it. |
passwordPrompt.hint says which password to ask for ('user' or 'owner'), when the engine
knows. When the state is 'required', passwordPrompt.incorrect is true if the last password
you tried was wrong.
A locked document still opens: without a password, open() succeeds, and every call that reads
the file fails with DocPasswordRequired until you unlock it. A wrong password doesn’t fail
open() either: the document opens locked, and passwordPrompt.incorrect is true, so you can
say “that password is wrong” and ask again.
unlock() fails with DocPasswordIncorrect when the password is wrong, so you can ask again:
import { EngineError, EngineErrorCode } from '@cloudpdf/engine';
while (doc.security.passwordPrompt.state === 'required') {
try {
await doc.security.unlock({ password: await askUserForPassword() });
} catch (error) {
if (!EngineError.is(error, EngineErrorCode.DocPasswordIncorrect)) throw error;
showMessage('That password is wrong. Try again.');
}
}Owner password#
A PDF can have two passwords. The user password opens it; the owner password also lifts the
file’s own restrictions, such as “no printing” or “no copying”. When a file is open but not with
its owner password, passwordPrompt is 'optional'.
To accept only the owner password, pass mode: 'owner'. The user password then fails with
DocPasswordIncorrect:
await doc.security.unlock({ password, mode: 'owner' });The file’s own restrictions only count when the user’s permissions include pdf.permissions;
see Permissions.
On the cloud, who the user is and what they may do come from their token, so open() has no
options for them. See What a token carries.
Close a document#
Close a document when you’re done with it:
await doc.close();Closing stops the live updates for this document and forgets what the engine cached. The document
itself stays on the server. After it, calls on doc fail with DocNotOpen. Closing twice is
fine.
One engine, many documents#
Create one engine for your app and open every document on it:
const [contract, invoice] = await Promise.all([
engine.open(contractInput),
engine.open(invoiceInput),
]);Keep the engine for as long as your app runs. When you do want to shut it down, at the end of a script for example, destroy it; that also closes every document still open on it:
await engine.destroy();Each document keeps the token it was opened with, so one engine can hold documents opened for different users or with different permissions.
Good to know#
Cancelling an open#
open() returns a promise you can cancel, like every call:
const opening = engine.open(input);
cancelButton.onclick = () => opening.abort();See Errors & cancelling.