Commit a7bf420dd5ec74285bfd220c02a4a99e8bc2e7ce

Authored by Marko Tikvić
1 parent 9ede5c7a90
Exists in master

added document utility

Showing 1 changed file with 219 additions and 0 deletions   Show diff stats
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