Commit a7bf420dd5ec74285bfd220c02a4a99e8bc2e7ce
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 |