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
... ... @@ -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 +}
... ...