Compare View

switch
from
...
to
 
Commits (2)
document/document.go
File was created 1 package document
2
3 import (
4 "errors"
5 "fmt"
6 "io"
7 "mime"
8 "net/http"
9 "os"
10 "strings"
11 "time"
12
13 web "git.to-net.rs/marko.tikvic/webutility"
14 )
15
16 // Document ...
17 type Document struct {
18 ID int64 `json:"id"`
19 FileName string `json:"fileName"`
20 Extension string `json:"extension"`
21 ContentType string `json:"contentType"`
22 Size int64 `json:"fileSize"`
23 UploadedBy string `json:"uploadedBy"`
24 LastModifiedBy string `json:"lastModifiedBy"`
25 TimeUploaded int64 `json:"timeUploaded"`
26 TimeLastModified int64 `json:"timeLastModified"`
27 RoleAccessLevel int64 `json:"accessLevel"`
28 Description string `json:"description"`
29 Download *DownloadLink `json:"download"`
30 Path string `json:"-"`
31 directory string
32 data []byte
33 }
34
35 // OpenFileAsDocument ...
36 func OpenFileAsDocument(path string) (*Document, error) {
37 d := &Document{Path: path}
38
39 f, err := os.Open(d.Path)
40 if err != nil {
41 return nil, err
42 }
43 defer f.Close()
44
45 stats, err := f.Stat()
46 if err != nil {
47 return nil, err
48 }
49
50 d.FileName = stats.Name()
51 d.Size = stats.Size()
52 d.Extension = FileExtension(d.FileName)
53
54 d.data = make([]byte, d.Size)
55 if _, err = f.Read(d.data); err != nil {
56 return nil, err
57 }
58
59 return d, err
60 }
61
62 // DownloadLink ...
63 type DownloadLink struct {
64 Method string `json:"method"`
65 URL string `json:"url"`
66 }
67
68 // SetDownloadInfo ...
69 func (d *Document) SetDownloadInfo(method, url string) {
70 d.Download = &DownloadLink{
71 Method: method,
72 URL: url,
73 }
74 }
75
76 // ServeDocument writes d's buffer to w and sets appropriate headers according to d's content type
77 // and downloadPrompt.
78 func ServeDocument(w http.ResponseWriter, d *Document, downloadPrompt bool) error {
79 f, err := os.Open(d.Path)
80 if err != nil {
81 return err
82 }
83 defer f.Close()
84
85 web.SetContentType(w, mime.TypeByExtension(d.Extension))
86 web.SetResponseStatus(w, http.StatusOK)
87 if downloadPrompt {
88 w.Header().Set("Content-Disposition", "attachment; filename="+d.FileName)
89 }
90
91 buf := make([]byte, d.Size)
92 if _, err := f.Read(buf); err != nil {
93 return err
94 }
95
96 w.Header().Set("Content-Length", fmt.Sprintf("%d", d.Size))
97 web.WriteResponse(w, buf)
98
99 return nil
100 }
101
102 // FileExists ...
103 func FileExists(path string) bool {
104 temp, err := os.Open(path)
105 defer temp.Close()
106
107 if err != nil {
108 return false
109 }
110
111 return true
112 }
113
114 // ParseDocument ...
115 func ParseDocument(req *http.Request) (doc *Document, err error) {
116 req.ParseMultipartForm(32 << 20)
117 file, fheader, err := req.FormFile("document")
118 if err != nil {
119 return doc, err
120 }
121
122 claims, _ := web.GetTokenClaims(req)
123 owner := claims.Username
124
125 fname := fheader.Filename
126
127 fsize := fheader.Size
128 ftype := fmt.Sprintf("%v", fheader.Header["Content-Type"][0])
129
130 fextn := FileExtension(fname)
131 if fextn == "" {
132 return doc, errors.New("invalid extension")
133 }
134
135 doc = new(Document)
136
137 doc.FileName = fname
138 doc.Size = fsize
139 doc.ContentType = ftype
140 doc.Extension = "." + fextn
141
142 t := time.Now().Unix()
143 doc.TimeUploaded = t
144 doc.TimeLastModified = t
145
146 doc.UploadedBy = owner
147 doc.LastModifiedBy = owner
148 doc.RoleAccessLevel = 0
149
150 doc.data = make([]byte, doc.Size)
151 if _, err = io.ReadFull(file, doc.data); err != nil {
152 return doc, err
153 }
154
155 return doc, nil
156 }
157
158 // DirectoryFromPath ...
159 func DirectoryFromPath(path string) (dir string) {
160 parts := strings.Split(path, "/")
161 if len(parts) == 1 {
162 return ""
163 }
164
165 dir = parts[0]
166 for _, p := range parts[1 : len(parts)-1] {
167 dir += "/" + p
168 }
169
170 return dir
171 }
172
173 // SaveToFile ...
174 func (d *Document) SaveToFile(path string) (f *os.File, err error) {
175 d.Path = path
176
177 if FileExists(path) {
178 err = fmt.Errorf("file %s alredy exists", path)
179 return nil, err
180 }
181
182 if parentDir := DirectoryFromPath(path); parentDir != "" {
183 if err = os.MkdirAll(parentDir, os.ModePerm); err != nil {
184 if !os.IsExist(err) {
185 return nil, err
186 }
187 }
188 }
189
190 if f, err = os.Create(path); err != nil {
191 return nil, err
192 }
193
194 if _, err = f.Write(d.data); err != nil {
195 f.Close()
196 d.DeleteFile()
197 return nil, err
198 }
199 f.Close()
200
201 return f, nil
202 }
203
204 func DeleteFile(path string) error {
205 return os.Remove(path)
206 }
207
208 // DeleteFile ...
209 func (d *Document) DeleteFile() error {
210 return os.Remove(d.Path)
211 }
212
213 func FileExtension(path string) string {
214 parts := strings.Split(path, ".") // because name can contain dots
215 if len(parts) < 2 {
216 return ""
217 }
218 return "." + parts[len(parts)-1]
219 }
220
1 package pdfhelper 1 package pdfhelper
2 2
3 import ( 3 import (
4 "fmt" 4 "fmt"
5 "strings" 5 "strings"
6 6
7 "git.to-net.rs/marko.tikvic/gofpdf" 7 "git.to-net.rs/marko.tikvic/gofpdf"
8 ) 8 )
9 9
10 // Block ... 10 // Block ...
11 const ( 11 const (
12 CENTER = "C" 12 CENTER = "C"
13 LEFT = "L" 13 LEFT = "L"
14 RIGHT = "R" 14 RIGHT = "R"
15 TOP = "T" 15 TOP = "T"
16 BOTTOM = "B" 16 BOTTOM = "B"
17 FULL = "1" 17 FULL = "1"
18 NOBORDER = "" 18 NOBORDER = ""
19 ) 19 )
20 20
21 const ( 21 const (
22 CONTINUE = 0 22 CONTINUE = 0
23 NEWLINE = 1 23 NEWLINE = 1
24 BELLOW = 2 24 BELLOW = 2
25 ) 25 )
26 26
27 const ( 27 const (
28 cyrillicEncoding = "cp1251" 28 cyrillicEncoding = "cp1251"
29 latinEncoding = "cp1250" 29 latinEncoding = "cp1250"
30 ) 30 )
31 31
32 const threeDots = "\u2056\u2056\u2056"
33
34 type TableCell struct {
35 W, H float64
36 Text string
37 Font, FontStyle string
38 FontSize float64
39 Border string
40 Alignment string
41 }
42
32 const threeDots = "\u2056\u2056\u2056" 43 // Helper ...
33 44 type Helper struct {
34 type TableCell struct { 45 *gofpdf.Fpdf
35 W, H float64 46 translators map[string]func(string) string
36 Text string 47 }
37 Font, FontStyle string 48
38 FontSize float64 49 // New ...
39 Border string 50 func New(ori, unit, size string) *Helper {
40 Alignment string 51 helper := &Helper{
41 } 52 Fpdf: gofpdf.New(ori, unit, size, ""),
42 53 }
43 // Helper ... 54
44 type Helper struct { 55 return helper
45 *gofpdf.Fpdf 56 }
46 translators map[string]func(string) string 57
47 } 58 func (pdf *Helper) LoadTranslators() {
48 59 pdf.translators = make(map[string]func(string) string)
49 // New ... 60 pdf.translators[latinEncoding] = pdf.UnicodeTranslatorFromDescriptor(latinEncoding)
50 func New(ori, unit, size string) *Helper { 61 pdf.translators[cyrillicEncoding] = pdf.UnicodeTranslatorFromDescriptor(cyrillicEncoding)
51 helper := &Helper{ 62 }
52 Fpdf: gofpdf.New(ori, unit, size, ""), 63
53 } 64 func (pdf *Helper) DrawCell(x, y float64, c TableCell) {
54
55 return helper
56 }
57
58 func (pdf *Helper) LoadTranslators() {
59 pdf.translators = make(map[string]func(string) string)
60 pdf.translators[latinEncoding] = pdf.UnicodeTranslatorFromDescriptor(latinEncoding)
61 pdf.translators[cyrillicEncoding] = pdf.UnicodeTranslatorFromDescriptor(cyrillicEncoding)
62 }
63
64 func (pdf *Helper) DrawCell(x, y float64, c TableCell) {
65 pdf.SetXY(x, y)
66 pdf.SetFont(c.Font, c.FontStyle, c.FontSize)
67 pdf.CellFormat(c.W, c.H, pdf.toUTF8(c.Text), c.Border, BELLOW, c.Alignment, false, 0, "")
68 }
69
70 func (pdf *Helper) DrawColumn(x, y float64, cells []TableCell) {
71 pdf.SetXY(x, y)
72 for _, c := range cells {
73 pdf.SetFont(c.Font, c.FontStyle, c.FontSize)
74 pdf.CellFormat(c.W, c.H, pdf.toUTF8(c.Text), c.Border, BELLOW, c.Alignment, false, 0, "")
75 }
76 }
77
78 func (pdf *Helper) DrawRow(x, y float64, cells []TableCell) {
79 pdf.SetXY(x, y)
80 for _, c := range cells {
81 pdf.SetFont(c.Font, c.FontStyle, c.FontSize)
82 pdf.CellFormat(c.W, c.H, pdf.toUTF8(c.Text), c.Border, CONTINUE, c.Alignment, false, 0, "")
83 }
84 }
85
86 func (pdf *Helper) TextLength(txt, family, style string, size float64) float64 {
87 family, _, _, _ = pdf.setCorrectFontFamily(textEncoding(txt))
88 return pdf.Fpdf.TextLength(txt, family, style, size)
89 }
90
91 func (pdf *Helper) LimitText(text, limiter string, maxWidth float64) string {
92 parts := pdf.Fpdf.SplitText(text, maxWidth)
93 if len(parts) > 1 {
94 return parts[0] + limiter
95 }
96
97 return text
98 }
99
100 // InsertImage ...
101 func (pdf *Helper) InsertImage(img string, x, y, w, h float64) {
102 imgType := ""
103 if parts := strings.Split(img, "."); len(parts) >= 2 {
104 imgType = parts[len(parts)-1]
105 }
106 opt := gofpdf.ImageOptions{ 65 pdf.SetXY(x, y)
107 ImageType: imgType, 66 pdf.SetFont(c.Font, c.FontStyle, c.FontSize)
108 ReadDpi: false, 67 pdf.CellFormat(c.W, c.H, pdf.toUTF8(c.Text), c.Border, BELLOW, c.Alignment, false, 0, "")
109 AllowNegativePosition: false, 68 }
110 } 69
111 autoBreak := false // if it's not false then you can't draw the image at an arbitrary height (y position) 70 func (pdf *Helper) DrawColumn(x, y float64, cells []TableCell) {
112 pdf.ImageOptions(img, x, y, w, h, autoBreak, opt, 0, "") 71 pdf.SetXY(x, y)
113 } 72 for _, c := range cells {
114 73 pdf.SetFont(c.Font, c.FontStyle, c.FontSize)
115 func (pdf *Helper) PageHasSpace(requiredHeight float64) bool { 74 pdf.CellFormat(c.W, c.H, pdf.toUTF8(c.Text), c.Border, BELLOW, c.Alignment, false, 0, "")
116 _, h := pdf.GetPageSize()
117 _, _, _, bot := pdf.GetMargins() 75 }
118 return (h - bot - pdf.GetY()) > requiredHeight 76 }
119 } 77
120 78 func (pdf *Helper) DrawRow(x, y float64, cells []TableCell) {
121 // DrawBox ...
122 func (pdf Helper) DrawBox(x0, y0, w, h float64) {
123 pdf.Line(x0, y0, x0+w, y0)
124 pdf.Line(x0+w, y0, x0+w, y0+h)
125 pdf.Line(x0+w, y0+h, x0, y0+h)
126 pdf.Line(x0, y0+h, x0, y0)
127 }
128
129 // Strana %d/{TotalPages}
130 func (pdf *Helper) InsertPageNumber(x, y float64, format string) {
131 num := fmt.Sprintf(format, pdf.PageNo())
132 pdf.DrawColumn(x, y, []TableCell{{10, 1, num, "DejaVuSans", "", 8, NOBORDER, LEFT}})
133 } 79 pdf.SetXY(x, y)
134 80 for _, c := range cells {
135 func (pdf *Helper) SuperscriptText(x, y, cw, ch float64, text, script string) { 81 pdf.SetFont(c.Font, c.FontStyle, c.FontSize)
136 family, style, size, sizeU := pdf.setCorrectFontFamily(textEncoding(text)) 82 pdf.CellFormat(c.W, c.H, pdf.toUTF8(c.Text), c.Border, CONTINUE, c.Alignment, false, 0, "")
137 83 }
138 pdf.DrawCell(x, y, TableCell{cw, ch, text, family, style, size, NOBORDER, LEFT}) 84 }
139 85
140 sx := x + pdf.TextLength(text, family, style, size) 86 func (pdf *Helper) TextLength(txt, family, style string, size float64) float64 {
141 sy := y - sizeU*0.2 87 family, _, _, _ = pdf.setCorrectFontFamily(textEncoding(txt))
142 pdf.DrawCell(sx, sy, TableCell{cw, ch, script, family, style, size - 2, NOBORDER, LEFT}) 88 return pdf.Fpdf.TextLength(txt, family, style, size)
143 }
144
145 // toUTF8 ...
146 func (pdf *Helper) toUTF8(s string) string {
147 encoding := textEncoding(s)
148 pdf.setCorrectFontFamily(encoding)
149 translator, ok := pdf.translators[encoding]
150 if !ok {
151 return ""
152 }
153 return translator(s) 89 }
154 } 90
155 91 func (pdf *Helper) LimitText(text, limiter string, maxWidth float64) string {
156 func textEncoding(s string) string { 92 parts := pdf.Fpdf.SplitText(text, maxWidth)
157 encoding := latinEncoding 93 if len(parts) > 1 {
158 runes := []rune(s) 94 return parts[0] + limiter
159 for _, r := range runes { 95 }
160 if uint64(r) >= 0x0402 && uint64(r) <= 0x044f { 96
161 encoding = cyrillicEncoding 97 return text
162 break 98 }
163 } 99
164 } 100 // InsertImage ...
165 return encoding 101 func (pdf *Helper) InsertImage(img string, x, y, w, h float64) {
166 } 102 imgType := ""
167 103 if parts := strings.Split(img, "."); len(parts) >= 2 {
168 func (pdf *Helper) setCorrectFontFamily(enc string) (family, style string, ptSize, unitSize float64) { 104 imgType = parts[len(parts)-1]
169 family, style, ptSize, unitSize = pdf.GetFontInfo() 105 }
170 if enc == cyrillicEncoding { 106 opt := gofpdf.ImageOptions{
171 if !strings.HasSuffix(family, "cyrillic") { 107 ImageType: imgType,