-
Notifications
You must be signed in to change notification settings - Fork 0
/
poppler.go
116 lines (104 loc) · 2.65 KB
/
poppler.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
//go:build poppler
package main
import (
"errors"
"io"
"strconv"
"strings"
"time"
"github.com/gabriel-vasile/mimetype"
"github.com/johbar/go-poppler"
"github.com/johbar/text-extraction-service/v2/pkg/dehyphenator"
)
type Pdf struct {
*poppler.Document
}
func init() {
pdfImplementation = "Poppler (GLib) version " + poppler.Version()
}
func NewFromStream(stream io.ReadCloser) (doc *Pdf, err error) {
data, err := io.ReadAll(stream)
if err != nil {
logger.Error("Could not fully read stream when constructing Poppler document", "err", err)
}
stream.Close()
return NewFromBytes(data)
}
func NewFromBytes(data []byte) (doc *Pdf, err error) {
if mimetype.Detect(data).Extension() != ".pdf" {
return &Pdf{nil}, errors.New("not a PDF")
}
pDoc, err := poppler.Load(data)
if err != nil {
logger.Error("Poppler could not load PDF", "err", err)
}
doc = &Pdf{pDoc}
return
}
// Text returns the plain text content of the document
func (d *Pdf) Text() string {
var buf strings.Builder
for n := 0; n < d.GetNPages(); n++ {
page := d.GetPage(n)
buf.WriteString(page.Text())
page.Close()
}
return buf.String()
}
// StreamText writes the document's plain text content to an io.Writer
func (d *Pdf) StreamText(w io.Writer) {
logger.Debug("Extracting", "pages", d.GetNPages())
finished := make(chan bool)
pr, pw := io.Pipe()
go func() {
dehyphenator.DehyphenateReaderToWriter(pr, w)
pr.Close()
finished <- true
}()
for n := 0; n < d.GetNPages(); n++ {
page := d.GetPage(n)
pw.Write([]byte(page.Text()))
// ensure there is a newline at the end of every page
pw.Write([]byte{'\n'})
page.Close()
}
pw.Close()
<-finished
}
// Metadata returns some of the PDF metadata as map with keys compatible to HTTP headers
func (d *Pdf) MetadataMap() map[string]string {
m := make(map[string]string)
m["x-parsed-by"] = "Poppler"
m["x-doctype"] = "pdf"
info := d.Info()
if info.Pages != 0 {
m["x-document-pages"] = strconv.Itoa(info.Pages)
}
if info.PdfVersion != "" {
m["x-document-version"] = info.PdfVersion
}
if info.Author != "" {
m["x-document-author"] = info.Author
}
if info.Title != "" {
m["x-document-title"] = info.Title
}
if info.Subject != "" {
m["x-document-subject"] = info.Subject
}
if info.KeyWords != "" {
m["x-document-keywords"] = info.KeyWords
}
if info.CreationDate != 0 {
createTime := time.Unix(int64(info.CreationDate), 0)
m["x-document-created"] = createTime.Format(time.RFC3339)
}
if info.ModificationDate != 0 {
modTime := time.Unix(int64(info.ModificationDate), 0)
m["x-document-modified"] = modTime.Format(time.RFC3339)
}
return m
}
func (d *Pdf) DocInfo() poppler.DocumentInfo {
return d.Info()
}