ledongthuc/pdf
| Language | Go |
|---|---|
| License | BSD-3-Clause |
| Repository | github.com/ledongthuc/pdf |
| Documentation | pkg.go.dev/github.com/ledongthuc/pdf |
| Depends on | nothing (pure Go) |
| Read / write | yes (text, page objects) / no |
ledongthuc/pdf is a fork of Russ Cox’s rsc.io/pdf reader with text-extraction helpers. It parses the PDF object structure, decodes Flate streams and maps font encodings (including ToUnicode CMaps) to text. It’s small, has no dependencies and no cgo, which makes it handy for indexing and simple extraction in Go services.
It’s a reader only, and limited: no rendering, no layout analysis beyond grouping by rows, weak support for some encrypted files and unusual fonts. The repository has no tagged releases, so go get records a pseudo-version. For accurate text from complex documents, use go-fitz (MuPDF) or an external tool like pdftotext.
Installation#
go get github.com/ledongthuc/pdf
Basic usage: extract plain text#
package main
import (
"bytes"
"fmt"
"log"
"github.com/ledongthuc/pdf"
)
func main() {
f, r, err := pdf.Open("in.pdf")
if err != nil {
log.Fatal(err)
}
defer f.Close()
fmt.Printf("%d pages\n", r.NumPage())
plain, err := r.GetPlainText() // io.Reader with the text of all pages
if err != nil {
log.Fatal(err)
}
var buf bytes.Buffer
if _, err := buf.ReadFrom(plain); err != nil {
log.Fatal(err)
}
fmt.Println(buf.String())
}
How to get text with fonts and positions#
GetStyledTexts returns text runs with their font name, size and coordinates:
texts, err := r.GetStyledTexts()
if err != nil {
log.Fatal(err)
}
for _, t := range texts {
fmt.Printf("%q font=%s size=%.1f x=%.1f y=%.1f\n", t.S, t.Font, t.FontSize, t.X, t.Y)
}
How to extract text page by page, grouped by rows#
for i := 1; i <= r.NumPage(); i++ {
p := r.Page(i)
if p.V.IsNull() {
continue
}
rows, err := p.GetTextByRow()
if err != nil {
log.Printf("page %d: %v", i, err)
continue
}
for _, row := range rows {
var line string
for _, word := range row.Content {
line += word.S
}
fmt.Printf("page %d, row %d: %s\n", i, row.Position, line)
}
}
p.GetPlainText(fonts) returns the text of a single page; pass nil to let it load the page’s fonts.
How to read the document information dictionary#
The Trailer() method gives access to raw PDF objects:
info := r.Trailer().Key("Info")
for _, key := range []string{"Title", "Author", "Producer"} {
if v := info.Key(key); !v.IsNull() {
fmt.Printf("%s: %s\n", key, v.Text())
}
}
Tips#
pdf.NewReader(readerAt, size)reads from memory or anyio.ReaderAtinstead of a file.- Wrap extraction in
recover()when processing untrusted files: the parser can panic on malformed input. pdf.DebugOn = truelogs parsing details.