Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

187 lines
4.4KB

  1. package main
  2. import (
  3. "biukop.com/sfm/loan"
  4. "crypto/sha256"
  5. "errors"
  6. "fmt"
  7. log "github.com/sirupsen/logrus"
  8. "io"
  9. "io/ioutil"
  10. "net/http"
  11. "os"
  12. "path/filepath"
  13. "strconv"
  14. "time"
  15. )
  16. func apiV1UploadsGet(w http.ResponseWriter, r *http.Request, ss *loan.Session) {
  17. id := r.URL.Path[len(apiV1Prefix+"lender-upload/"):] //remove prefix
  18. intId, e := strconv.Atoi(id)
  19. if e != nil {
  20. log.Println("invalid id for upload get", id, e)
  21. apiV1Client403Error(w, r, ss) // bad request
  22. return
  23. }
  24. ul := loan.Uploads{}
  25. e = ul.Read(int64(intId))
  26. if e != nil {
  27. log.Println("no file uploaded", intId, e)
  28. apiV1Client404Error(w, r, ss) // bad request
  29. return
  30. }
  31. //check local file first
  32. path := config.Uploads + strconv.FormatInt(ul.Id, 10) + ".uploads"
  33. if fileExists(path) {
  34. http.ServeFile(w, r, path)
  35. return
  36. }
  37. log.Error("Upload file not found on disk", ul)
  38. apiV1Server500Error(w, r) // bad request
  39. }
  40. func apiV1UploadsPost(w http.ResponseWriter, r *http.Request, ss *loan.Session) {
  41. id := r.URL.Path[len(apiV1Prefix+"lender-upload/"):] //remove prefix
  42. filename, e := saveUploadToFile(r)
  43. if e != nil {
  44. log.Println("no file uploaded", filename, e)
  45. apiV1Client404Error(w, r, ss) // bad request
  46. return
  47. }
  48. intId, e := strconv.Atoi(id)
  49. if id != "" {
  50. if e != nil {
  51. log.Println("Error Getting File", e)
  52. apiV1Client404Error(w, r, ss) // bad request
  53. return
  54. }
  55. updateUploads(int64(intId), filename, w, r, ss)
  56. } else {
  57. createUploads(filename, w, r, ss)
  58. }
  59. }
  60. func sha256File(input io.Reader) string {
  61. hash := sha256.New()
  62. if _, err := io.Copy(hash, input); err != nil {
  63. log.Fatal(err)
  64. }
  65. sum := hash.Sum(nil)
  66. return fmt.Sprintf("%x", sum)
  67. }
  68. func updateUploads(id int64, fileName string, w http.ResponseWriter, r *http.Request, ss *loan.Session) {
  69. ul := loan.Uploads{}
  70. e := ul.Read(int64(id))
  71. if e != nil {
  72. log.Println("bad upload id is given ", id, e)
  73. apiV1Client404Error(w, r, ss) // bad request
  74. return
  75. }
  76. ul1, _, e := saveUploadsToDB(id, fileName, r, ss)
  77. if e != nil {
  78. os.Remove(config.Uploads + ul.FileName)
  79. ul1.Delete()
  80. log.Println("cannot save file info to db ", e)
  81. apiV1Server500Error(w, r) // bad request
  82. return
  83. }
  84. apiV1SendJson(ul1, w, r, ss)
  85. }
  86. func createUploads(fileName string, w http.ResponseWriter, r *http.Request, ss *loan.Session) {
  87. ul, _, e := saveUploadsToDB(0, fileName, r, ss)
  88. if e != nil {
  89. log.Println("cannot save file info to db ", e)
  90. e = ul.Delete() // delete the newly created, if failed, db will clean it
  91. if e != nil {
  92. log.Error("failed to remove unused uploads", ul)
  93. }
  94. e = os.Remove(config.Uploads + fileName)
  95. if e != nil {
  96. log.Error("failed to remove unused temp file", fileName)
  97. }
  98. apiV1Server500Error(w, r) // bad request
  99. return
  100. }
  101. apiV1SendJson(ul, w, r, ss)
  102. }
  103. func saveUploadsToDB(id int64, fileName string,
  104. r *http.Request, ss *loan.Session) (ul loan.Uploads, duplicate bool, e error) {
  105. duplicate = false
  106. e = r.ParseMultipartForm(10 << 20) // we should have ready parsed this, just in case
  107. if e != nil {
  108. return
  109. }
  110. file, header, e := r.FormFile("files")
  111. file.Seek(0, 0) //seek to beginning
  112. checksum := sha256File(file)
  113. ul.Id = id
  114. ul.Ts = time.Now()
  115. ul.FileName = header.Filename
  116. file.Seek(0, 0) //seek to beginning
  117. ul.Format = header.Header.Get("Content-type")
  118. ul.Size = header.Size // necessary to prevent duplicate
  119. ul.LastModified = 0
  120. ul.Sha256 = checksum // necessary to prevent duplicate
  121. ul.By = ss.User
  122. e = ul.Write() // this Id will have the real Id if there is duplicates
  123. if e != nil {
  124. log.Error("Fail to update db ", ul, e)
  125. } else {
  126. if id > 0 && ul.Id != id {
  127. duplicate = true
  128. }
  129. target := fmt.Sprintf("%d.uploads", ul.Id)
  130. e = os.Rename(config.Uploads+fileName, config.Uploads+target)
  131. if e != nil {
  132. ul.FileName = fileName // some how failed to rename
  133. }
  134. }
  135. return
  136. }
  137. func saveUploadToFile(r *http.Request) (filename string, e error) {
  138. e = r.ParseMultipartForm(10 << 20)
  139. if e != nil {
  140. return
  141. }
  142. file, header, e := r.FormFile("files")
  143. if e != nil {
  144. log.Println("Error Getting File", e)
  145. return
  146. }
  147. out, pathError := ioutil.TempFile(config.Uploads, "can-del-upload-*.tmp")
  148. if pathError != nil {
  149. log.Println("Error Creating a file for writing", pathError)
  150. return
  151. }
  152. out.Seek(0, 0) //seek to beginning
  153. size, e := io.Copy(out, file)
  154. if e != nil {
  155. os.Remove(out.Name()) //remove on failure
  156. log.Println("Error copying", e)
  157. return
  158. }
  159. if size != header.Size {
  160. e = errors.New("written file with incorrect size")
  161. }
  162. return filepath.Base(out.Name()), e
  163. }