Compare View

switch
from
...
to
 
Commits (2)
document/document.go
... ... @@ -0,0 +1,219 @@
  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 +}
... ...
... ... @@ -29,6 +29,17 @@ const (
29 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 43 // Helper ...
33 44 type Helper struct {
34 45 *gofpdf.Fpdf
... ... @@ -50,106 +61,31 @@ func (pdf *Helper) LoadTranslators() {
50 61 pdf.translators[cyrillicEncoding] = pdf.UnicodeTranslatorFromDescriptor(cyrillicEncoding)
51 62 }
52 63  
53   -// InsertTab ...
54   -func (pdf *Helper) InsertTab(count int, w, h float64) {
55   - for i := 0; i < count; i++ {
56   - pdf.Cell(w, h, "")
57   - }
58   -}
59   -
60   -// CellWithBox ...
61   -func (pdf *Helper) CellWithBox(w, h float64, text, align string) {
62   - //pdf.drawCellMargins(w, h)
63   - //pdf.Cell(w, h, text)
64   - pdf.CellFormat(w, h, pdf.ToUTF8(text), FULL, CONTINUE, align, false, 0, "")
65   -}
66   -
67   -func (pdf *Helper) CellWithMargins(w, h float64, text, align string, index, of int) {
68   - len := of - 1
69   - border := ""
70   -
71   - // if top cell
72   - if index == 0 {
73   - border += "T"
74   - }
75   -
76   - border += "LR" // always draw these
77   -
78   - // if bottom cell
79   - if index == len {
80   - border += "B"
81   - }
82   -
83   - pdf.CellFormat(w, h, pdf.ToUTF8(text), border, CONTINUE, align, false, 0, "")
84   -}
85   -
86   -// MultiRowCellWithBox ...
87   -func (pdf *Helper) MultiRowCellWithBox(w, h float64, text []string, align string) {
88   - pdf.drawCellMargins(w, h*float64(len(text)))
89   - for i := range text {
90   - pdf.CellFormat(w, h, pdf.ToUTF8(text[i]), "", BELLOW, align, false, 0, "")
91   - }
92   -}
93   -
94   -// CellFormat(w, h, text, borders, newLine, fill)
95   -
96   -type FormatedCell struct {
97   - W, H float64
98   - Text string
99   - Font, FontStyle string
100   - FontSize float64
101   - Border string
102   - Alignment string
103   -}
104   -
105   -func (pdf *Helper) FCell(x, y float64, c FormatedCell) {
  64 +func (pdf *Helper) DrawCell(x, y float64, c TableCell) {
106 65 pdf.SetXY(x, y)
107 66 pdf.SetFont(c.Font, c.FontStyle, c.FontSize)
108   - pdf.CellFormat(c.W, c.H, pdf.ToUTF8(c.Text), c.Border, BELLOW, c.Alignment, false, 0, "")
  67 + pdf.CellFormat(c.W, c.H, pdf.toUTF8(c.Text), c.Border, BELLOW, c.Alignment, false, 0, "")
109 68 }
110 69  
111   -func (pdf *Helper) Column(x, y float64, cells []FormatedCell) {
  70 +func (pdf *Helper) DrawColumn(x, y float64, cells []TableCell) {
112 71 pdf.SetXY(x, y)
113 72 for _, c := range cells {
114 73 pdf.SetFont(c.Font, c.FontStyle, c.FontSize)
115   - pdf.CellFormat(c.W, c.H, pdf.ToUTF8(c.Text), c.Border, BELLOW, c.Alignment, false, 0, "")
116   - //pdf.CellFormat(c.w, c.h, c.text, c.border, BELLOW, align, false, 0, "")
  74 + pdf.CellFormat(c.W, c.H, pdf.toUTF8(c.Text), c.Border, BELLOW, c.Alignment, false, 0, "")
117 75 }
118 76 }
119 77  
120   -// NewLine ...
121   -func (pdf *Helper) NewLine(h float64) {
122   - pdf.Ln(h)
123   -}
124   -
125   -// WriteColumns ...
126   -func (pdf *Helper) WriteColumns(align string, cols []PDFCell) {
127   - for _, c := range cols {
128   - pdf.CellFormat(c.width, c.height, pdf.ToUTF8(c.data), "", CONTINUE, align, false, 0, "")
129   - }
130   -}
131   -
132   -func (pdf *Helper) Row(x, y float64, cells []FormatedCell) {
  78 +func (pdf *Helper) DrawRow(x, y float64, cells []TableCell) {
133 79 pdf.SetXY(x, y)
134 80 for _, c := range cells {
135 81 pdf.SetFont(c.Font, c.FontStyle, c.FontSize)
136   - pdf.CellFormat(c.W, c.H, pdf.ToUTF8(c.Text), c.Border, CONTINUE, c.Alignment, false, 0, "")
  82 + pdf.CellFormat(c.W, c.H, pdf.toUTF8(c.Text), c.Border, CONTINUE, c.Alignment, false, 0, "")
137 83 }
138 84 }
139 85  
140   -const threeDots = "\u2056\u2056\u2056"
141   -
142   -// WriteColumnsWithAlignment ...
143   -func (pdf *Helper) WriteColumnsWithAlignment(cols []PDFCellAligned) {
144   - for _, c := range cols {
145   - lines := pdf.SplitText(c.data, c.width)
146   - if len(lines) == 1 {
147   - pdf.CellFormat(c.width, c.height, pdf.ToUTF8(lines[0]), "", CONTINUE, c.alignment, false, 0, "")
148   - } else {
149   - pdf.CellFormat(c.width, c.height, pdf.ToUTF8(lines[0]+threeDots), "", CONTINUE, c.alignment, false, 0, "")
150   - }
151   - }
152   -
  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)
153 89 }
154 90  
155 91 func (pdf *Helper) LimitText(text, limiter string, maxWidth float64) string {
... ... @@ -176,22 +112,45 @@ func (pdf *Helper) InsertImage(img string, x, y, w, h float64) {
176 112 pdf.ImageOptions(img, x, y, w, h, autoBreak, opt, 0, "")
177 113 }
178 114  
179   -// PDFCell ...
180   -type PDFCell struct {
181   - data string
182   - height, width float64
  115 +func (pdf *Helper) PageHasSpace(requiredHeight float64) bool {
  116 + _, h := pdf.GetPageSize()
  117 + _, _, _, bot := pdf.GetMargins()
  118 + return (h - bot - pdf.GetY()) > requiredHeight
183 119 }
184 120  
185   -// PDFCellAligned ...
186   -type PDFCellAligned struct {
187   - alignment string
188   - data string
189   - height, width float64
  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)
190 127 }
191 128  
192   -func (pdf *Helper) TextLength(txt, family, style string, size float64) float64 {
193   - family, _, _, _ = pdf.setCorrectFontFamily(textEncoding(txt))
194   - return pdf.Fpdf.TextLength(txt, family, style, size)
  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 +}
  134 +
  135 +func (pdf *Helper) SuperscriptText(x, y, cw, ch float64, text, script string) {
  136 + family, style, size, sizeU := pdf.setCorrectFontFamily(textEncoding(text))
  137 +
  138 + pdf.DrawCell(x, y, TableCell{cw, ch, text, family, style, size, NOBORDER, LEFT})
  139 +
  140 + sx := x + pdf.TextLength(text, family, style, size)
  141 + sy := y - sizeU*0.2
  142 + pdf.DrawCell(sx, sy, TableCell{cw, ch, script, family, style, size - 2, NOBORDER, LEFT})
  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)
195 154 }
196 155  
197 156 func textEncoding(s string) string {
... ... @@ -206,17 +165,6 @@ func textEncoding(s string) string {
206 165 return encoding
207 166 }
208 167  
209   -// ToUTF8 ...
210   -func (pdf *Helper) ToUTF8(s string) string {
211   - encoding := textEncoding(s)
212   - pdf.setCorrectFontFamily(encoding)
213   - translator, ok := pdf.translators[encoding]
214   - if !ok {
215   - return ""
216   - }
217   - return translator(s)
218   -}
219   -
220 168 func (pdf *Helper) setCorrectFontFamily(enc string) (family, style string, ptSize, unitSize float64) {
221 169 family, style, ptSize, unitSize = pdf.GetFontInfo()
222 170 if enc == cyrillicEncoding {
... ... @@ -231,46 +179,3 @@ func (pdf *Helper) setCorrectFontFamily(enc string) (family, style string, ptSiz
231 179 pdf.SetFont(family, style, ptSize)
232 180 return family, style, ptSize, unitSize
233 181 }
234   -
235   -func (pdf *Helper) PageHasSpace(requiredHeight float64) bool {
236   - _, h := pdf.GetPageSize()
237   - _, _, _, bot := pdf.GetMargins()
238   - return (h - bot - pdf.GetY()) > requiredHeight
239   -}
240   -
241   -func (pdf *Helper) imageCenterOffset(w, h float64) (x, y float64) {
242   - pageW, pageH := pdf.GetPageSize()
243   - x = pageW/2.0 - w/2.0
244   - y = pageH/2.0 - h/2.0
245   - return x, y
246   -}
247   -
248   -// call before drawing the cell
249   -func (pdf *Helper) drawCellMargins(cw, ch float64) {
250   - x0, y0 := pdf.GetX(), pdf.GetY()
251   - pdf.DrawBox(x0, y0, cw, ch)
252   -}
253   -
254   -// DrawBox ...
255   -func (pdf Helper) DrawBox(x0, y0, w, h float64) {
256   - pdf.Line(x0, y0, x0+w, y0)
257   - pdf.Line(x0+w, y0, x0+w, y0+h)
258   - pdf.Line(x0+w, y0+h, x0, y0+h)
259   - pdf.Line(x0, y0+h, x0, y0)
260   -}
261   -
262   -// Strana %d/{TotalPages}
263   -func (pdf *Helper) InsertPageNumber(x, y float64, format string) {
264   - num := fmt.Sprintf(format, pdf.PageNo())
265   - pdf.Column(x, y, []FormatedCell{{10, 1, num, "DejaVuSans", "", 8, NOBORDER, LEFT}})
266   -}
267   -
268   -func (pdf *Helper) SuperscriptText(x, y, cw, ch float64, text, script string) {
269   - family, style, size, sizeU := pdf.setCorrectFontFamily(textEncoding(text))
270   -
271   - pdf.FCell(x, y, FormatedCell{cw, ch, text, family, style, size, NOBORDER, LEFT})
272   -
273   - sx := x + pdf.TextLength(text, family, style, size)
274   - sy := y - sizeU*0.2
275   - pdf.FCell(sx, sy, FormatedCell{cw, ch, script, family, style, size - 2, NOBORDER, LEFT})
276   -}
... ...