API de streams do Node.js
O binding nativo pdf-oxide oferece streams legíveis para resultados de busca, páginas e tabelas — idiomáticos para pipelines do Node.js e eficientes em memória para documentos grandes.
Todos os streams implementam a interface padrão Readable do Node.js em modo de objeto, oferecem suporte a backpressure, integram-se com pipe() e funcionam com a iteração assíncrona for await.
Os streams são nativos do binding do Node.js. Para o build WASM, itere de forma síncrona.
SearchStream
Emite um SearchResult por vez à medida que o SearchManager subjacente produz correspondências.
const { PdfDocument, SearchManager, SearchStream } = require("pdf-oxide");
const doc = new PdfDocument("large.pdf");
const manager = new SearchManager(doc);
const stream = new SearchStream(manager, "invoice");
stream.on("data", (r) => {
console.log(`page ${r.pageIndex + 1}: ${r.text}`);
});
stream.on("end", () => {
console.log("search complete");
doc.close();
});
stream.on("error", (err) => {
console.error(err);
doc.close();
});
Busca com diferenciação de maiúsculas e minúsculas
const stream = new SearchStream(manager, "Invoice", { caseSensitive: true });
Iteração assíncrona
for await (const result of stream) {
if (result.pageIndex > 50) break;
console.log(result.text);
}
Compatibilidade com pipe()
const { Writable } = require("stream");
const sink = new Writable({
objectMode: true,
write(result, _enc, cb) {
console.log(`${result.pageIndex}:${result.text}`);
cb();
},
});
stream.pipe(sink);
PageIteratorStream
Emite o texto extraído de uma página por vez. Útil para saída orientada a linhas ou ao alimentar um LLM com uma fila limitada por taxa (rate-limited).
const { PageIteratorStream } = require("pdf-oxide");
const stream = new PageIteratorStream(doc, { format: "markdown" });
for await (const { pageIndex, content } of stream) {
await indexPage(pageIndex, content);
}
format aceita "text" (padrão), "markdown", "html", "plain".
TableStream
Emite uma tabela por vez, à medida que é detectada.
const { TableStream } = require("pdf-oxide");
const stream = new TableStream(doc);
stream.on("data", (table) => {
console.log(`${table.rows.length}x${table.rows[0].length} on page ${table.pageIndex}`);
});
Backpressure
Todos os streams implementam o backpressure padrão do Node.js. Se o seu consumidor for lento, o stream pausa a extração até que .read() retome:
stream.on("data", async (result) => {
stream.pause();
await slowIndex(result);
stream.resume();
});
Ou use for await, que cuida da pausa automaticamente.
Tratamento de erros
Erros durante a extração são emitidos como eventos error padrão:
stream.on("error", (err) => {
if (err.code === "PDF_INVALID_PAGE") {
console.warn("skipping invalid page", err.pageIndex);
} else {
throw err;
}
});
Eficiência de memória
Os streams mantêm apenas um resultado em trânsito. Em um PDF de 10.000 páginas que produz 50.000 correspondências, um SearchStream usa memória constante — o conjunto inteiro de resultados nunca é materializado.
Limpeza
Fechar o PdfDocument pai encerra todos os streams associados. Os streams também liberam a referência ao seu manager em end / error.
const doc = new PdfDocument("big.pdf");
const stream = new SearchStream(new SearchManager(doc), "TODO");
stream.on("end", () => doc.close());
stream.on("error", () => doc.close());
No Node.js 22+, a palavra-chave using libera o documento quando o escopo é encerrado:
{
using doc = new PdfDocument("big.pdf");
const stream = new SearchStream(new SearchManager(doc), "TODO");
for await (const r of stream) console.log(r);
} // doc.close() called automatically
Relacionados
- Primeiros passos com Node.js — instalação e início rápido
- Referência da API do Node.js
- Busca — opções de busca sem streaming