-
Notifications
You must be signed in to change notification settings - Fork 0
/
mupdf.go
123 lines (108 loc) · 2.65 KB
/
mupdf.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
117
118
119
120
121
122
123
//go:build mupdf
package main
import (
"io"
"strconv"
"strings"
"github.com/gen2brain/go-fitz"
"github.com/johbar/text-extraction-service/v2/pkg/dehyphenator"
"github.com/johbar/text-extraction-service/v2/pkg/pdfdateparser"
)
type Pdf struct {
*fitz.Document
}
func init() {
pdfImplementation = "MuPDF (go-fitz)"
}
func NewFromBytes(data []byte) (*Pdf, error) {
fdoc, err := fitz.NewFromMemory(data)
if err != nil {
logger.Error(err.Error())
}
logger.Debug("Opened doc", "pages", fdoc.NumPage())
return &Pdf{fdoc}, err
}
func NewFromStream(stream io.Reader) (Pdf, error) {
fdoc, err := fitz.NewFromReader(stream)
if err != nil {
logger.Error(err.Error())
}
logger.Debug("Opened Doc", "Pages", fdoc.NumPage())
return Pdf{fdoc}, err
}
func (d *Pdf) Text() string {
result := ""
for i := 0; i <= d.NumPage(); i++ {
pText, err := d.Document.Text(i)
if err != nil {
logger.Error(err.Error())
}
result += pText
}
return result
}
func (d *Pdf) StreamText(w io.Writer) {
pr, pw := io.Pipe()
finished := make(chan bool)
go func() {
dehyphenator.DehyphenateReaderToWriter(pr, w)
pr.Close()
finished <- true
}()
for i := 0; i < d.NumPage(); i++ {
pText, err := d.Document.Text(i)
if err != nil {
logger.Error(err.Error())
continue
}
pw.Write([]byte(pText))
// ensure there is a newline at the end of every page
pw.Write([]byte{'\n'})
}
pw.Close()
<-finished
}
func (d *Pdf) GetNPages() int {
return d.Document.NumPage()
}
func (d *Pdf) MetadataMap() map[string]string {
m := d.Document.Metadata()
r := make(map[string]string)
if val := stripNulls(m["format"]); val != "" {
r["x-document-version"] = val
}
if val := stripNulls(m["author"]); val != "" {
r["x-document-author"] = val
}
if val := stripNulls(m["title"]); val != "" {
r["x-document-title"] = val
}
if val := stripNulls(m["subject"]); val != "" {
r["x-document-subject"] = val
}
if val := stripNulls(m["keywords"]); val != "" {
r["x-document-keywords"] = val
}
r["x-document-pages"] = strconv.Itoa(d.NumPage())
if d, _ := pdfdateparser.PdfDateToIso(stripNulls(m["creationDate"])); len(d) > 0 {
r["x-document-created"] = d
}
if d, _ := pdfdateparser.PdfDateToIso(stripNulls(m["modDate"])); len(d) > 0 {
r["x-document-modified"] = d
}
if val := stripNulls(m["producer"]); val != "" {
r["x-document-producer"] = val
}
if val := stripNulls(m["creator"]); val != "" {
r["x-document-creator"] = val
}
r["x-parsed-by"] = "MuPDF"
return r
}
// go-fitz seems to return Strings of 256 length with zero byte padding
func stripNulls(val string) string {
return strings.ReplaceAll(val, "\u0000", "")
}
func (d Pdf) Close() {
d.Document.Close()
}