Primeros pasos con PDF Oxide (WASM)
PDF Oxide se compila a WebAssembly para correr en navegadores, Deno, Bun y runtimes edge como Cloudflare Workers o Vercel Edge. El mismo núcleo en Rust que impulsa los bindings de Python, Rust, Node.js, Go y C# funciona directamente en cualquier entorno JavaScript, con rendimiento cercano al nativo.
¿Usas Node.js? Para servidores Node.js prefiere el addon nativo N-API
pdf-oxide: es más rápido y añade OCR, renderizado y firmas digitales. El build WASM de esta página es la opción adecuada para navegadores y runtimes edge donde los addons nativos no pueden cargarse.
Instalación
npm install pdf-oxide-wasm
import { WasmPdfDocument, WasmPdf } from "pdf-oxide-wasm";
Inicio rápido
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();
Navegador
<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>
Navegador con selector de archivo
<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>
Extracción de texto
Una sola página
const doc = new WasmPdfDocument(bytes);
const text = doc.extractText(0);
Todas las páginas
const allText = doc.extractAllText();
Extracción estructurada
Datos a nivel de carácter y de span, con posiciones y metadatos de fuente:
// Datos por carácter
const chars = doc.extractChars(0);
for (const c of chars) {
console.log(`'${c.char}' at (${c.bbox.x}, ${c.bbox.y}) font=${c.fontName}`);
}
// Datos por span
const spans = doc.extractSpans(0);
for (const span of spans) {
console.log(`"${span.text}" size=${span.fontSize}`);
}
Conversión a Markdown
const markdown = doc.toMarkdown(0);
// Con opciones
const md = doc.toMarkdown(0, true, true); // detect_headings, include_images
// Todas las páginas
const allMarkdown = doc.toMarkdownAll();
Conversión a HTML
const html = doc.toHtml(0);
// Todas las páginas
const allHtml = doc.toHtmlAll();
Creación de PDF
Genera nuevos PDFs a partir de Markdown, HTML o texto plano con WasmPdf:
import { WasmPdf } from "pdf-oxide-wasm";
// Desde Markdown
const pdf = WasmPdf.fromMarkdown("# Hello World\n\nThis is a PDF.");
const pdfBytes = pdf.toBytes(); // Uint8Array
// Desde HTML
const invoice = WasmPdf.fromHtml("<h1>Invoice</h1><p>Amount: $42</p>");
// Desde texto plano
const notes = WasmPdf.fromText("Plain text content.");
// Guardar a archivo (Node.js)
import { writeFileSync } from "fs";
writeFileSync("output.pdf", pdf.toBytes());
Campos de formulario
const fields = doc.getFormFields();
for (const f of fields) {
console.log(`${f.name} (${f.fieldType}) = ${f.value}`);
}
// Exportar datos del formulario
const fdfBytes = doc.exportFormData(); // formato FDF
const xfdfBytes = doc.exportFormData("xfdf"); // formato XFDF
Búsqueda
// Buscar en todas las páginas
const results = doc.search("configuration", true); // case_insensitive
for (const r of results) {
console.log(`Found "${r.text}" on page ${r.page}`);
}
// Buscar en una sola página
const pageResults = doc.searchPage(0, "configuration", true);
Abrir desde bytes
El constructor de WasmPdfDocument ya acepta un Uint8Array directamente; no hace falta un método from_bytes aparte:
// Ya funciona: WasmPdfDocument recibe los bytes
const doc = new WasmPdfDocument(uint8Array);
PDFs cifrados
const doc = new WasmPdfDocument(encryptedBytes);
const success = doc.authenticate("password");
if (success) {
console.log(doc.extractText(0));
}
Edición
const doc = new WasmPdfDocument(bytes);
// Metadatos
doc.setTitle("Updated Title");
doc.setAuthor("Jane Doe");
// Rotación de página
doc.rotatePage(0, 90);
// Guardar con cambios
const edited = doc.save();
// Guardar cifrado
const encrypted = doc.saveEncryptedToBytes(
"user-password",
"owner-password",
true, // allow_print
true, // allow_copy
false, // allow_modify
true // allow_annotate
);
Gestión de memoria
Los objetos WASM retienen memoria de Rust que debe liberarse explícitamente:
const doc = new WasmPdfDocument(bytes);
try {
const text = doc.extractText(0);
} finally {
doc.free();
}
Disponibilidad de funciones
Algunas funciones requieren dependencias nativas y no están disponibles en la compilación WebAssembly:
| Función | WASM | Notas |
|---|---|---|
| Extracción de texto | Sí | Soporte completo |
| Creación de PDF | Sí | Markdown, HTML, texto |
| Edición de PDF | Sí | Soporte completo |
| Cifrado | Sí | AES-256 |
| OCR | No | Requiere ONNX Runtime nativo |
| Firmas digitales | No | Requiere librerías de criptografía nativas |
| Renderizado de páginas | No | Requiere tiny-skia nativo |
Para OCR o renderizado usa los bindings de Python o Rust.
Siguientes pasos
- Primeros pasos en Python – usar PDF Oxide desde Python
- Primeros pasos en Rust – usar PDF Oxide desde Rust
- Referencia de API JavaScript – documentación completa de la API WASM
- Extracción de texto – opciones detalladas de extracción
- Creación de PDF – creación avanzada