Documentation
¶
Overview ¶
Package pdftext draws the readable text out of a PDF.
It exists because no pure-Go library reads the PDFs people actually upload. Both candidates were measured against real documents before this package was written, and both failed on the same 384 KB report: rsc.io/pdf panicked with "malformed PDF: reading at offset 0: stream not present", and github.com/dslipak/pdf spun at full CPU for over three minutes before it was killed. On the documents they did read, rsc.io/pdf emitted no spaces between text runs, which is not text a reader can use. github.com/pdfcpu/pdfcpu decodes content streams but extracts no text at all.
What does work is PDFium, Chrome's PDF engine, compiled to WebAssembly and run under wazero. It reads the same file in milliseconds with word spacing and line breaks intact. It costs a one-time module compile at startup and about ten megabytes of binary, and it is cgo-free, so the static build is unaffected.
Lifetime ¶
The module compile costs about a second and happens once, on the first PDF a deployment is asked to read, not at startup: a deployment that never meets one never pays for it. Close releases the pool. A deployment builds one Extractor and shares it, because the compile is the expensive part and every extraction after it is cheap.
Index ¶
Constants ¶
This section is empty.
Variables ¶
ErrUnavailable reports that no extractor is usable: a nil one, or one that has been closed. A caller that never built an extractor takes the same path as one whose document could not be parsed.
Functions ¶
This section is empty.
Types ¶
type Extractor ¶
type Extractor struct {
// contains filtered or unexported fields
}
Extractor reads text out of PDF documents. It is safe for concurrent use: each extraction takes an instance from the pool for its duration.
The zero value is not usable; build one with New.
func New ¶
func New() *Extractor
New returns an Extractor. It does no work: the PDFium module is compiled on the first document, so a deployment that is never asked to read a PDF never pays the second it costs.
func (*Extractor) Close ¶
Close releases the pool and every instance in it. It is safe to call on an Extractor that never compiled its module, and safe to call twice.
func (*Extractor) ExtractText ¶
ExtractText returns the document's text, page by page in document order, stopping once it has produced limit bytes. Pages are separated by a blank line, which is what keeps the last line of one page from running into the first line of the next.
An error means the bytes could not be read as a PDF. A PDF that parses but holds no text -- a scan, a deck of images -- is not an error: it returns the empty string, and the caller decides what an empty document means.