Skip to content

Знакомство с PDF Oxide (WASM)

PDF Oxide компилируется в WebAssembly и работает в браузере, Deno, Bun и edge-рантаймах (Cloudflare Workers, Vercel Edge). То же ядро на Rust, на котором построены биндинги для Python, Rust, Node.js, Go и C#, напрямую исполняется в любой JavaScript-среде с почти нативной скоростью.

Работаете с Node.js? На сервере используйте нативный N-API-аддон pdf-oxide — он быстрее и поддерживает OCR, рендеринг и подписи. WASM-сборка с этой страницы подходит для браузера и edge-рантаймов, где нативные аддоны не загружаются.

Установка

npm install pdf-oxide-wasm
import { WasmPdfDocument, WasmPdf } from "pdf-oxide-wasm";

Быстрый старт

Node.js

import { readFileSync } from "fs";
import { WasmPdfDocument } from "pdf-oxide-wasm";

const bytes = new Uint8Array(readFileSync("document.pdf"));
const doc = new WasmPdfDocument(bytes);

console.log(`Pages: ${doc.pageCount()}`);
console.log(doc.extractText(0));

doc.free();

Браузер

<script type="module">
import init, { WasmPdfDocument } from "pdf-oxide-wasm";

await init();

const response = await fetch("document.pdf");
const bytes = new Uint8Array(await response.arrayBuffer());
const doc = new WasmPdfDocument(bytes);

console.log(`Pages: ${doc.pageCount()}`);
console.log(doc.extractText(0));
doc.free();
</script>

Браузер с выбором файла

<input type="file" id="pdfInput" accept=".pdf" />
<pre id="output"></pre>

<script type="module">
import init, { WasmPdfDocument } from "pdf-oxide-wasm";
await init();

document.getElementById("pdfInput").addEventListener("change", async (e) => {
  const file = e.target.files[0];
  const bytes = new Uint8Array(await file.arrayBuffer());
  const doc = new WasmPdfDocument(bytes);

  let result = `Pages: ${doc.pageCount()}\n\n`;
  for (let i = 0; i < doc.pageCount(); i++) {
    result += `--- Page ${i + 1} ---\n`;
    result += doc.extractText(i) + "\n\n";
  }

  document.getElementById("output").textContent = result;
  doc.free();
});
</script>

Извлечение текста

Одна страница

const doc = new WasmPdfDocument(bytes);
const text = doc.extractText(0);

Все страницы

const allText = doc.extractAllText();

Структурированное извлечение

Данные по символам и спанам с координатами и метаданными шрифтов:

// Данные по символам
const chars = doc.extractChars(0);
for (const c of chars) {
  console.log(`'${c.char}' at (${c.bbox.x}, ${c.bbox.y}) font=${c.fontName}`);
}

// Данные по спанам
const spans = doc.extractSpans(0);
for (const span of spans) {
  console.log(`"${span.text}" size=${span.fontSize}`);
}

Конвертация в Markdown

const markdown = doc.toMarkdown(0);

// С параметрами
const md = doc.toMarkdown(0, true, true); // detect_headings, include_images

// Все страницы
const allMarkdown = doc.toMarkdownAll();

Конвертация в HTML

const html = doc.toHtml(0);

// Все страницы
const allHtml = doc.toHtmlAll();

Создание PDF

Создавайте новые PDF из Markdown, HTML или обычного текста через WasmPdf:

import { WasmPdf } from "pdf-oxide-wasm";

// Из Markdown
const pdf = WasmPdf.fromMarkdown("# Hello World\n\nThis is a PDF.");
const pdfBytes = pdf.toBytes(); // Uint8Array

// Из HTML
const invoice = WasmPdf.fromHtml("<h1>Invoice</h1><p>Amount: $42</p>");

// Из обычного текста
const notes = WasmPdf.fromText("Plain text content.");

// Сохранить в файл (Node.js)
import { writeFileSync } from "fs";
writeFileSync("output.pdf", pdf.toBytes());

Поля форм

const fields = doc.getFormFields();
for (const f of fields) {
  console.log(`${f.name} (${f.fieldType}) = ${f.value}`);
}

// Экспорт данных формы
const fdfBytes = doc.exportFormData();        // формат FDF
const xfdfBytes = doc.exportFormData("xfdf"); // формат XFDF

Поиск

// Поиск по всем страницам
const results = doc.search("configuration", true); // case_insensitive
for (const r of results) {
  console.log(`Found "${r.text}" on page ${r.page}`);
}

// Поиск на одной странице
const pageResults = doc.searchPage(0, "configuration", true);

Открытие из байтов

Конструктор WasmPdfDocument сразу принимает Uint8Array — отдельный метод from_bytes не нужен:

// Уже работает — WasmPdfDocument принимает байты
const doc = new WasmPdfDocument(uint8Array);

Зашифрованные PDF

const doc = new WasmPdfDocument(encryptedBytes);
const success = doc.authenticate("password");
if (success) {
  console.log(doc.extractText(0));
}

Редактирование

const doc = new WasmPdfDocument(bytes);

// Метаданные
doc.setTitle("Updated Title");
doc.setAuthor("Jane Doe");

// Поворот страницы
doc.rotatePage(0, 90);

// Сохранение изменений
const edited = doc.save();

// Сохранение с шифрованием
const encrypted = doc.saveEncryptedToBytes(
  "user-password",
  "owner-password",
  true,   // allow_print
  true,   // allow_copy
  false,  // allow_modify
  true    // allow_annotate
);

Управление памятью

WASM-объекты удерживают Rust-память, которую нужно освобождать явно:

const doc = new WasmPdfDocument(bytes);
try {
  const text = doc.extractText(0);
} finally {
  doc.free();
}

Доступность функций

Некоторые возможности требуют нативных зависимостей и недоступны в сборке WebAssembly:

Функция WASM Примечания
Извлечение текста Да Полная поддержка
Создание PDF Да Markdown, HTML, текст
Редактирование PDF Да Полная поддержка
Шифрование Да AES-256
OCR Нет Нужен нативный ONNX Runtime
Электронные подписи Нет Нужны нативные крипто-библиотеки
Рендеринг страниц Нет Нужен нативный tiny-skia

Для OCR или рендеринга используйте биндинги Python или Rust.

Дальше