|
- package main
-
- import (
- "biukop.com/sfm/loan"
- "crypto/sha256"
- "errors"
- "fmt"
- log "github.com/sirupsen/logrus"
- "io"
- "io/ioutil"
- "net/http"
- "os"
- "path/filepath"
- "strconv"
- "time"
- )
-
- func apiV1UploadsGet(w http.ResponseWriter, r *http.Request, ss *loan.Session) {
- id := r.URL.Path[len(apiV1Prefix+"lender-upload/"):] //remove prefix
- intId, e := strconv.Atoi(id)
- if e != nil {
- log.Println("invalid id for upload get", id, e)
- apiV1Client403Error(w, r, ss) // bad request
- return
- }
-
- ul := loan.Uploads{}
- e = ul.Read(int64(intId))
- if e != nil {
- log.Println("no file uploaded", intId, e)
- apiV1Client404Error(w, r, ss) // bad request
- return
- }
-
- //check local file first
- path := config.Uploads + strconv.FormatInt(ul.Id, 10) + ".uploads"
- if fileExists(path) {
- http.ServeFile(w, r, path)
- return
- }
-
- log.Error("Upload file not found on disk", ul)
- apiV1Server500Error(w, r) // bad request
- }
-
- func apiV1UploadsPost(w http.ResponseWriter, r *http.Request, ss *loan.Session) {
- id := r.URL.Path[len(apiV1Prefix+"lender-upload/"):] //remove prefix
-
- filename, e := saveUploadToFile(r)
- if e != nil {
- log.Println("no file uploaded", filename, e)
- apiV1Client404Error(w, r, ss) // bad request
- return
- }
-
- intId, e := strconv.Atoi(id)
- if id != "" {
- if e != nil {
- log.Println("Error Getting File", e)
- apiV1Client404Error(w, r, ss) // bad request
- return
- }
- updateUploads(int64(intId), filename, w, r, ss)
- } else {
- createUploads(filename, w, r, ss)
- }
- }
-
- func sha256File(input io.Reader) string {
- hash := sha256.New()
- if _, err := io.Copy(hash, input); err != nil {
- log.Fatal(err)
- }
- sum := hash.Sum(nil)
-
- return fmt.Sprintf("%x", sum)
- }
-
- func updateUploads(id int64, fileName string, w http.ResponseWriter, r *http.Request, ss *loan.Session) {
- ul := loan.Uploads{}
- e := ul.Read(int64(id))
- if e != nil {
- log.Println("bad upload id is given ", id, e)
- apiV1Client404Error(w, r, ss) // bad request
- return
- }
-
- ul1, _, e := saveUploadsToDB(id, fileName, r, ss)
- if e != nil {
- os.Remove(config.Uploads + ul.FileName)
- ul1.Delete()
- log.Println("cannot save file info to db ", e)
- apiV1Server500Error(w, r) // bad request
- return
- }
-
- apiV1SendJson(ul1, w, r, ss)
- }
-
- func createUploads(fileName string, w http.ResponseWriter, r *http.Request, ss *loan.Session) {
- ul, _, e := saveUploadsToDB(0, fileName, r, ss)
- if e != nil {
- log.Println("cannot save file info to db ", e)
- e = ul.Delete() // delete the newly created, if failed, db will clean it
- if e != nil {
- log.Error("failed to remove unused uploads", ul)
- }
-
- e = os.Remove(config.Uploads + fileName)
- if e != nil {
- log.Error("failed to remove unused temp file", fileName)
- }
-
- apiV1Server500Error(w, r) // bad request
- return
- }
- apiV1SendJson(ul, w, r, ss)
- }
-
- func saveUploadsToDB(id int64, fileName string,
- r *http.Request, ss *loan.Session) (ul loan.Uploads, duplicate bool, e error) {
- duplicate = false
- e = r.ParseMultipartForm(10 << 20) // we should have ready parsed this, just in case
- if e != nil {
- return
- }
- file, header, e := r.FormFile("files")
-
- file.Seek(0, 0) //seek to beginning
- checksum := sha256File(file)
- ul.Id = id
- ul.Ts = time.Now()
- ul.FileName = header.Filename
- file.Seek(0, 0) //seek to beginning
- ul.Format = header.Header.Get("Content-type")
- ul.Size = header.Size // necessary to prevent duplicate
- ul.LastModified = 0
- ul.Sha256 = checksum // necessary to prevent duplicate
- ul.By = ss.User
- e = ul.Write() // this Id will have the real Id if there is duplicates
-
- if e != nil {
- log.Error("Fail to update db ", ul, e)
- } else {
- if id > 0 && ul.Id != id {
- duplicate = true
- }
- target := fmt.Sprintf("%d.uploads", ul.Id)
- e = os.Rename(config.Uploads+fileName, config.Uploads+target)
- if e != nil {
- ul.FileName = fileName // some how failed to rename
- }
- }
- return
- }
-
- func saveUploadToFile(r *http.Request) (filename string, e error) {
- e = r.ParseMultipartForm(10 << 20)
- if e != nil {
- return
- }
- file, header, e := r.FormFile("files")
- if e != nil {
- log.Println("Error Getting File", e)
- return
- }
-
- out, pathError := ioutil.TempFile(config.Uploads, "can-del-upload-*.tmp")
- if pathError != nil {
- log.Println("Error Creating a file for writing", pathError)
- return
- }
-
- out.Seek(0, 0) //seek to beginning
- size, e := io.Copy(out, file)
- if e != nil {
- os.Remove(out.Name()) //remove on failure
- log.Println("Error copying", e)
- return
- }
-
- if size != header.Size {
- e = errors.New("written file with incorrect size")
- }
- return filepath.Base(out.Name()), e
- }
|