embed-pdf-viewer

embedpdf活跃维护

一个可嵌入任意 JavaScript 项目的 PDF 查看器,基于 pdfium 和 pdfjs,支持 Angular 等前端框架,帮你在网页里直接渲染和操作 PDF 文档。

A PDF viewer that seamlessly integrates with any JavaScript project

v3.1.0发布于 2026-11-08 19:20 UTC4,590star +7 / 7 天328fork同步于 2026-11-10 11:37 UTC

怎么上手

从 README 代码块原样提取,可能是其中一种安装方式
npm install @embedpdf/viewer-react
硬件要求

README 没有说明硬件要求。

下载:源码 zip·GitHub Releases(安装包)本站不镜像安装包

项目说明

这个项目的说明还在生成中,先参考下面「最近发版」和 README。

最近发版

5 个版本v3.1.0
  1. v3.1.0Release v3.1.0最新正式版2026-11-08 · 2026-11-08 19:20 UTC

    @cloudpdf/[email protected]

    Minor Changes

    • #1030 by @bobsingor – The manifest and a write's cache delta carry viewportsVersion, the pin of the pages' scales. The page layout carries each page's viewports, and doc.pages.setScale answers with the new layout. The changes endpoint takes the pages.setScale op. The page list and the measurement viewport are named components.

    @cloudpdf/[email protected]

    Minor Changes

    • #1030 by @bobsingor – The layout is read at the manifest's viewportsVersion as well as its layoutVersion, so it carries the pages' scales and a scale change reaches every client. page.measure.setScale() is a one-page doc.pages.setScale change.

    • #1033 by @bobsingor – A token function now runs once per token, not once per request. The engine keeps the token it gives, and calls the function again in the background a minute before that token expires, so no request waits for the renewal and a long session never runs out. Requests that arrive together share one call; a renewal that fails is tried again 5 seconds later while the kept token still works. When CloudPDF refuses a kept token, the engine asks the function once more and sends the request again. A literal token works as before.

    @cloudpdf/[email protected]

    Minor Changes

    • #1030 by @bobsingor – The types carry viewportsVersion on the manifest and a write's cache delta, viewports on a page's layout, the pages.setScale change op and its answer, and the new layout in doc.pages.setScale's answer.

    @cloudpdf/[email protected]

    Minor Changes

    • #1030 by @bobsingor – Layers and versions keep viewports_version (migration 053), raised by a scale change and by nothing else, so the outline, search and export caches stay warm across one. The layout's cached URL carries it; a token without it gets the layout without viewports. PUT …/pages/:pageKey/scale is a one-op change, so its opId undoes it. The changes endpoint applies pages.setScale.

    @cloudpdf/[email protected]

    Minor Changes

    • #1033 by @bobsingor – src: { id, token } keeps the document open when src changes but its id doesn't, and takes the next token from the new src. A token function written inline in a component, made again on every render, no longer reopens the document.

    @embedpdf/[email protected]

    Minor Changes

    • #1029 by @bobsingor – ctx.storeChangeCount() says how many times the store changed: a state or mirror write anywhere, or a ctx.notify(), counted when the change happens, also while the change stream is held. Give it to memo or memoByKey as the input of a read whose answer comes from functions you can't name the inputs of, so the read asks them once per store change, however many readers ask. Test contexts from @embedpdf/core/testing have it too.

      memo and memoByKey compare their inputs with a plain loop, which makes every cached read a little cheaper.

    Patch Changes

    • #1030 by @bobsingor – The page list takes a page scale change's new layout from its event, and shows a pending one at once. The test context's pages can carry viewports, and a document event that moves them wakes the store's readers, as in the kernel.

    • #1028 by [@bobsingor](https://github.com/

  2. v3.0.0Release v3.0.02026-11-06 · 2026-11-06 23:04 UTC
    查看更新说明

    EmbedPDF 3.0 is EmbedPDF rebuilt, from the PDF engine up. There are three ways to use it:

    • The ready-made viewer. A complete PDF viewer you add with one tag, in plain HTML, React, Vue, Svelte or Angular, and make your own with a few lines of config. See the Quick start.
    • Headless components. Build your own viewer UI from the same plugins, with bindings for React, Vue, Svelte and Angular. See Headless components.
    • The EmbedPDF Engine. Open, read, change and render PDFs from your own code. It runs in the browser on WebAssembly, and in Node on native builds for macOS, Linux and Windows. See Engine.

    What the viewer does

    Every feature is on from the start, and each one can be turned off:

    • Annotations: highlight, underline and strike out text; draw; notes, text boxes and callouts; shapes; stamps; comments with replies.
    • Forms and signatures: fill in forms and build them; draw, type or upload a signature, sign fields, and check signatures.
    • Redaction: mark text and areas, then remove them from the file for good.
    • Measurement: distances, perimeters and areas at the drawing's scale.
    • Pages: rotate, move, insert, duplicate and delete pages, each step undoable.
    • Reading: search, text selection, thumbnails, the outline, attachments, snapshots, printing, downloading, and several documents in tabs.

    All features lists each one with its settings.

    Install

    npm install @embedpdf/viewer
    

    From a CDN: https://cdn.jsdelivr.net/npm/@embedpdf/viewer@3/dist/embedpdf.js. For React, Vue, Svelte and Angular, install @embedpdf/viewer-react, @embedpdf/viewer-vue, @embedpdf/viewer-svelte or @embedpdf/viewer-angular.

    Moving from 2.x

    • New package names. The viewer packages from 2.x, @embedpdf/snippet, @embedpdf/react-pdf-viewer, @embedpdf/vue-pdf-viewer and @embedpdf/svelte-pdf-viewer, are replaced by @embedpdf/viewer and its framework packages.
    • A guide, name by name. Moving from 2.x maps every 2.x package and config key to its 3.0 counterpart.
    • 2.x stays where it is. Its docs are at v2.embedpdf.com, and 2.x fixes publish under the npm tag v2-latest.

    CloudPDF

    CloudPDF, the company that makes EmbedPDF, publishes the @cloudpdf packages:

    • the same viewer for documents kept on a CloudPDF server (@cloudpdf/viewer, @cloudpdf/viewer-react, @cloudpdf/viewer-vue, @cloudpdf/viewer-svelte and @cloudpdf/viewer-angular);
    • the server itself (@cloudpdf/server), also published as the image ghcr.io/embedpdf/cloudpdf-server:3.0.0 and the Helm chart oci://ghcr.io/embedpdf/charts/cloudpdf-server;
    • an SDK for its API (@cloudpdf/sdk).

    See the server docs.

    Thanks

    Thanks to everyone who tried the next releases and told us what broke.

    Every package

    Each package's CHANGELOG.md has its full list of changes. The 3.0.0 entry gathers every change since 2.15.0. Every package is at 3.0.0, except the three font and stamp packages, which are at 1.0.0.

    The viewer: @embedpdf/viewer, @embedpdf/viewer-angular, @embedpdf/viewer-chrome, @embedpdf/viewer-react, @embedpdf/viewer-svelte, [@embedpdf/viewer-vue](http

  3. v3.0.0-next.23Release Next v3.0.0-next.23pre-release2026-11-06 · 2026-11-06 16:44 UTC
    查看更新说明

    @cloudpdf/[email protected]

    Minor Changes

    • #991 by @bobsingor – The manifest and a mutation's cacheDelta have contentsVersion, the document-wide pin of every page's content.

    • #989 by @bobsingor – GET …/head answers engine, the server's engine value for each kind of cached read. The manifest no longer has serverFonts.

    • #994 by @bobsingor – Every error response is the one error body, ErrorResponse, with its error EngineError; AdminErrorPayloadSchema and AdminThumbnailUnavailablePayloadSchema are gone, and a thumbnail that isn't ready says its state in details.state. Operations no longer get a type per error status, so a response type is named after its operation alone (DocFormsListResponse, not DocFormsList200Response). Sizes, counts, durations and the admin timestamps are integers. nextCursor, thumbnailState and thumbnailUrl are always there, and the license status's license, reporting and usage too (null when there's nothing). A union of whole-number literals, such as a rotation or a DocMDP level, is one integer enum in openapi.json.

    • #996 by @bobsingor – Every point in time is an ISO 8601 string (format: date-time): createdAt, updatedAt, archivedAt, lastExchangedAt, firstSeenAt, lastSeenAt and consentedAt on tenants, documents, folders, grants, layers and visitors, and every expiresAt (grants, the upload URL, tokens, grant sessions, download links), which were milliseconds in some places and seconds in others. A request gives one with its offset: a grant's expiresAt, and a token revoke's expiresAt, which replaces expiresAtSeconds. A date a write takes as a Date in process is a date-time string in openapi.json. A schema a model reuses no longer takes the nullable of the field that used it first: a grant's createdAt and updatedAt, and a visitor's firstSeenAt and lastSeenAt, read as non-null.

    • #997 by @bobsingor – Names and units follow one rule: a document's baseSha and storageSizeBytes are baseSha256 and sizeBytes, and so is a layer's and a visitor's layer's storageSizeBytes; the init request's contentLength and uploadTtlSec are sizeBytes and uploadTtlSeconds; token issue's and the download link's expiresIn is expiresInSeconds; folders move-into takes docIds (its 404 names details.docIds); usage metrics are pdfViews, pdfUploads and storageBytes, and a module's meters move to their own moduleMeters map; and the path parameters are {docId}, {annotationKey}, {sha256} and {displaySha256} (the URLs don't change).

    • #995 by @bobsingor – A destination's axes are always there, null to keep the viewer's value, and a document's openDestination is always there. A line's captionEnabled is a boolean, never null. A grant create takes null for origins and expiresAt, as a grant read says them, meaning any origin and no expiry.

    • #1005 by @bobsingor – A document head's permissions.flags (the named PdfPermissionFlags) replaces the raw bits word.

    • #982 by @bobsingor – A widget reads hasMark: true when it is a signature field's widget with a mark in it, because the field is signed or a mark was drawn in. Such a widget shows the mark, and a change to its style is refused.

    • #1002 by @bobsingor – The document init and import answers say what happened in status (created, resumed or deduped; imported, deduped or accepted), not tag, as every call's answer does. Form fields are tagged kind (was family) and a widget says fieldKind. The contract test checks that a union is tagged type, kind, status or subtype.

    • #992 by @bobsingor – Th

  4. v3.0.0-next.22Release Next v3.0.0-next.22pre-release2026-11-04 · 2026-11-04 14:13 UTC
    查看更新说明

    @cloudpdf/[email protected]

    Minor Changes

    • #978 by @bobsingor – Every markup annotation carries richText, its comment with formatting, or null for a plain comment, in reads, creates and updates. The rich text model is named once, as RichTextDocument and RichTextDocumentInput.

    • #967 by @bobsingor – deployment.modules (GET /v1/deployment/modules, API token) lists the installed server modules: ModuleManifest with its ModulePermissions and ModuleMeters, all named components. tenants.usage takes from and to (UTC days, to the day after the last) in place of period, and its metrics hold modules' meters next to the core's.

    • #971 by @bobsingor – A square, circle, polygon, polyline, line or ink annotation's color may be null: no stroke. A read gives null for a file's empty or missing stroke color.

    Patch Changes

    • #972 by @bobsingor – dashArray on an annotation's create and update and on a widget placement takes at least one length (minItems: 1): an empty pattern is refused.

    @cloudpdf/[email protected]

    Minor Changes

    • #978 by @bobsingor – Annotations, drafts and patches of every markup kind have richText, the comment with formatting (RichTextDocument, RichTextDocumentInput), or null for a plain comment.

    • #967 by @bobsingor – deployment.modules() lists the installed server modules: their names, permissions and meters. tenants.usage takes from and to for a window of UTC days, and its metrics include modules' meters.

    • #971 by @bobsingor – A square, circle, polygon, polyline, line or ink annotation's color may be null: no stroke.

    @cloudpdf/[email protected]

    Minor Changes

    • #967 by @bobsingor – Modules describe themselves, and count their usage. A module has a name (required) and a description, and declares meters (each with a label and a unit) that its routes count with req.meters.count(meter, { oncePerDay }) for the document's tenant. A permission can say how it relates to the core's: replaces (protected-display.view replaces doc.render) and bypassedBy (doc.download…), facts for a grant dialog that the server doesn't enforce; a token may hold a permission and the one it replaces, and the core one has its usual effect. GET /v1/deployment/modules lists the installed modules as they declare themselves, with the API token. Tenant usage is counted per UTC day: tenants.usage takes from and to in place of period, and reports each installed module's meters next to the core's. Migration 051 moves the counters to days (a month counted before keeps its total on its first day) and keeps the once-a-day keys as hashes, swept when the day is over.

    @cloudpdf/[email protected]

    Minor Changes

    • #967 by @bobsingor – defineServerModule takes a name (required), a description and meters; a request counts the module's meters with req.meters.count(meter, { oncePerDay }). Permissions take replaces and bypassedBy. startTestServer's tenant has the given modules turned on, so their routes answer instead of 403 FeatureNotEnabled.

    @embedpdf/[email protected]

    Minor Changes

    • [#97
  5. v3.0.0-next.21Release Next v3.0.0-next.21pre-release2026-11-03 · 2026-11-03 11:42 UTC
    查看更新说明

    @cloudpdf/[email protected]

    Minor Changes

    • #956 by @bobsingor – tenants.update (PATCH /v1/tenants/:tenantId) sets a tenant's features, the server modules it may use, and tenant records carry features. TenantFeature ({ id, stopped?: 'cap' }) is a named component.

    @cloudpdf/[email protected]

    Minor Changes

    • #956 by @bobsingor – tenants.update({ tenantId, features }) sets the server modules a tenant may use, and tenant records have features.

    @cloudpdf/[email protected]

    Minor Changes

    • #964 by @bobsingor – A Postgres connection that fails while idle in the pool no longer crashes the server. A database restart or failover, pg_terminate_backend, or a proxy closing the connection used to reach Node as an uncaught error event from pg.Pool. The pool now drops that connection and opens a new one for the next query. createPostgresDb takes onIdleConnectionError to report these, and cloudpdf-server logs each one's message as a warning.

    • #955 by @bobsingor – buildApp takes the deployment's license as license: the runtime createLicenseRuntime made, and nothing else. It replaces licenseGate. Any other object, including a copy of a runtime, stops the build with an error naming createLicenseRuntime. The runtime is sealed: its methods can't be replaced, and buildApp enforces the license from the runtime behind it. createLicenseRuntime takes only db, env, secretResolver and startTimer, and passes nothing else on, so license verification always uses the identity compiled into the package.

    • #956 by @bobsingor – Tenants have features: the server modules each tenant may use, by module id. A module's routes answer only tenants whose features hold it; others get 403 FeatureNotEnabled, and a feature held as { id, stopped: 'cap' } answers 402 FeatureStopped. A new tenant has none: the operator turns modules on per tenant with PATCH /v1/tenants/:tenantId (API token only, every id an installed module), and other replicas follow within 30 seconds. Migration 050 adds the column on SQLite and Postgres.

    @cloudpdf/[email protected]

    Minor Changes

    • #955 by @bobsingor – Test a module in a real server from published packages: startTestServer from @cloudpdf/server-modules/testing starts @cloudpdf/server with your modules mounted, on 127.0.0.1 with its own in-memory database, files and credentials, licensed by a development key (CLOUDPDF_LICENSE_KEY or licenseKey). addDocument(pdf) uploads a PDF through the server's upload API and answers its id and page keys; fetch(doc, path, { scope }) calls a route on the document's layer with a viewer token for exactly that scope; token() signs that token for a client of your own; apiToken calls as the deployment; close() removes everything. The kit also exports HostedModule, the type defineServerModule returns, so a module's declarations build with the kit as its only dependency.

    @embedpdf/[email protected]

    Minor Changes

    • #957 by @bobsingor – A floating bar's place takes hideWhenIdle (FloatPlace) in place of hideWhileScrolling, and hideWhenIdleOf(data, id) reads it in place of hideWhileScrollingOf, through the bar it rides along: the bar rests out of sight while nothing moves, instead of hiding while the pages scroll.

    @embedpdf/[email protected].

用户点评

登录用户的真实使用记录,可按版本和硬件筛选
共 0 条

    还没有人点评。第一个说出真实体验的人最有价值。

    README 原文

    未翻译

    Open-source PDF viewer for JavaScript

    EmbedPDF is a PDF viewer you add to any web app, in plain HTML, React, Vue, Svelte or Angular. People read, annotate, fill in, sign and redact PDFs right in the browser, on a PDF engine built on PDFium that runs as WebAssembly. Apache-2.0 licensed.

    Three ways to use it

    Quick start

    In plain HTML, from a CDN:

    <embedpdf-viewer src="https://www.embedpdf.com/pdfs/welcome.pdf" style="height: 100vh"></embedpdf-viewer>
    
    <script
      type="module"
      src="https://cdn.jsdelivr.net/npm/@embedpdf/viewer@3/dist/embedpdf.js"
    ></script>
    

    In React:

    npm install @embedpdf/viewer-react
    
    import { PDFViewer } from '@embedpdf/viewer-react';
    
    export function App() {
      return <PDFViewer src="https://www.embedpdf.com/pdfs/welcome.pdf" style={{ height: '100vh' }} />;
    }
    

    Vue, Svelte and Angular work the same way, with @embedpdf/viewer-vue, @embedpdf/viewer-svelte and @embedpdf/viewer-angular. The Quick start then shows how to use your colors, leave features out and add your own buttons.

    Features

    Every feature is on from the start, and each one can be turned off:

    • Annotations: highlight, underline and strike out text; draw; notes, text boxes and callouts; shapes; stamps; comments with replies.
    • Forms and signatures: fill in forms and build them; draw, type or upload a signature, sign fields, and check signatures.
    • Redaction: mark text and areas, then remove them from the file for good.
    • Measurement: distances, perimeters and areas at the drawing's scale.
    • Pages: rotate, move, insert, duplicate and delete pages, each step undoable.
    • Reading: search, text selection, thumbnails, the outline, attachments, snapshots, printing, downloading, and several documents in tabs.
    • Any language: Hebrew and Arabic work with no setup, right to left, and other scripts with a font of your own.

    Each feature is a plugin. The headless packages let you take only the ones you need.

    EmbedPDF and CloudPDF

    EmbedPDF is made by CloudPDF. Both are the same viewer, added to your app as a package. What differs is the engine behind it:

    What CloudPDF adds

    • Access control. Each user gets a token that says what they may do. View-only users never receive the file.
    • Collaboration. Annotations and comments are saved as people make them, and everyone sees them live.
    • Sharing. Public links that can expire, ask for a passphrase or work only on your sites.
    • Large files. The first page shows at once, without downloading the whole PDF.

    CloudPDF runs hosted, or on your own servers with its Docker image or Helm chart. See the CloudPDF docs.

    Sponsors

    We are grateful for the support of our sponsors!

    Silver Sponsors

    Bronze Sponsors

    Contributing

    We love contributions! To get started, read our contributing guide and jump into the GitHub discussions.

    License

    EmbedPDF: open source

    EmbedPDF is completely open source, under the Apache License 2.0: the viewer, the engine and every plugin, every @embedpdf/* package. Use it, change it and ship it in any app, commercial or not. (The handwriting fonts in @embedpdf/default-signature-fonts keep their own open license, the SIL Open Font License.)

    CloudPDF: open source, except the server

    Everything you build with CloudPDF is open source under the Apache License 2.0 too: the viewer (@cloudpdf/viewer and its framework packages), the engine (@cloudpdf/engine) and the SDK (@cloudpdf/sdk).

    The one exception is the server itself, cloudpdf/server. It is the product CloudPDF sells, so it is Fair Source, under the Fair Core License (FCL-1.0-ALv2):

    • You can read, copy and change its source for the purposes the FCL permits.
    • Running it needs a CloudPDF license: a license key for a connected server, or a signed certificate for an air-gapped one.
    • The license check stays in place. You may not move, change, disable or get around it, turn on protected features without a valid license, or remove protected features.
    • No competing use, as the FCL defines it: a product or service that substitutes for CloudPDF or offers the same or substantially similar functionality.
    • Each release becomes Apache 2.0 two years after it is published.

    LICENSING.md has the full map, including the websites' content and trademarks.

    Third-party licenses

    The engine is powered by EmbedPDF Runtime, our fork of PDFium, which is licensed under the Apache License, Version 2.0. PDFium is a Google project; EmbedPDF is not affiliated with or endorsed by Google.