package contented import ( "crypto/sha512" "encoding/hex" "io" "mime" "mime/multipart" "os" "path" "path/filepath" "strings" "time" ) func (this *Server) handleUpload(src multipart.File, hdr *multipart.FileHeader, UploadIP string) (string, error) { // Get file length srcLen, err := src.Seek(0, io.SeekEnd) if err != nil { return "", err } _, err = src.Seek(0, io.SeekStart) if err != nil { return "", err } // Get file hash hasher := sha512.New512_256() _, err = io.CopyN(hasher, src, int64(srcLen)) if err != nil { return "", err } _, err = src.Seek(0, io.SeekStart) if err != nil { return "", err } // Save file to disk fileID := hex.EncodeToString(hasher.Sum(nil)) dest, err := os.OpenFile(filepath.Join(this.opts.DataDirectory, fileID), os.O_CREATE|os.O_WRONLY, 0600) if err != nil { if os.IsExist(err) { return fileID, nil // hash matches existing upload } return "", err } defer dest.Close() _, err = io.CopyN(dest, src, int64(srcLen)) if err != nil { return "", err } // Determine mime type ctype := hdr.Header.Get("Content-Type") if ctype == "" { ctype = mime.TypeByExtension(path.Ext(hdr.Filename)) } if ctype == "" { ctype = `application/octet-stream` } // Blacklisted mime-types ctype = strings.ToLower(ctype) if strings.HasPrefix(ctype, `text/html`) || strings.HasPrefix(ctype, `application/javascript`) { ctype = `application/octet-stream` } // Persist metadata to DB m := Metadata{ Filename: hdr.Filename, UploadTime: time.Now(), UploadIP: UploadIP, FileSize: srcLen, MimeType: ctype, } err = this.SetMetadata(fileID, m) if err != nil { return "", err } // Done return fileID, nil }