選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

333 行
8.0KB

  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. "strconv"
  13. "strings"
  14. "time"
  15. )
  16. func apiV1UploadsGet(w http.ResponseWriter, r *http.Request, ss *loan.Session) {
  17. id := r.URL.Path[len(apiV1Prefix+"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 := uploadsOnDisk{}
  25. e = ul.Upload.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 := ul.filePath()
  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. filepath, e := saveUploadToFile(r)
  43. if e != nil {
  44. log.Println("no file uploaded", filepath, 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), filepath, w, r, ss)
  56. } else {
  57. createUploads(filepath, 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, filePath string, w http.ResponseWriter, r *http.Request, ss *loan.Session) {
  69. ul := uploadsOnDisk{}
  70. e := ul.Upload.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, isDuplicate, e := saveUploadsMetaToDB(id, filePath, r, ss)
  77. ul.Upload.IsDuplicate = isDuplicate
  78. if e != nil {
  79. os.Remove(ul.filePath())
  80. ul1.Delete()
  81. log.Println("cannot save file info to db ", e)
  82. apiV1Server500Error(w, r) // bad request
  83. return
  84. }
  85. apiV1SendJson(ul1, w, r, ss)
  86. }
  87. func createUploads(filePath string, w http.ResponseWriter, r *http.Request, ss *loan.Session) {
  88. ul := uploadsOnDisk{}
  89. ulMeta, isDuplicate, e := saveUploadsMetaToDB(0, filePath, r, ss)
  90. ul.Upload = ulMeta
  91. ul.Upload.IsDuplicate = isDuplicate
  92. if e != nil {
  93. log.Println("cannot save file info to db ", e)
  94. e = ulMeta.Delete() // delete the newly created, if failed, db will clean it
  95. if e != nil {
  96. log.Error("failed to remove unused uploads", ul)
  97. }
  98. e = os.Remove(ul.filePath())
  99. if e != nil {
  100. log.Error("failed to remove unused temp file", filePath)
  101. }
  102. apiV1Server500Error(w, r) // bad request
  103. return
  104. }
  105. ai := AiDecodeIncome{}
  106. ai.decodeUploadToPayIn(ul.Upload)
  107. apiV1SendJson(ai, w, r, ss)
  108. }
  109. func saveUploadsMetaToDB(id int64, filePath string,
  110. r *http.Request, ss *loan.Session) (ulMeta loan.Uploads, duplicate bool, e error) {
  111. duplicate = false
  112. e = r.ParseMultipartForm(10 << 20) // we should have ready parsed this, just in case
  113. if e != nil {
  114. return
  115. }
  116. file, header, e := r.FormFile("files")
  117. file.Seek(0, 0) //seek to beginning
  118. checksum := sha256File(file)
  119. ulMeta.Id = id
  120. ulMeta.Ts = time.Now()
  121. ulMeta.FileName = header.Filename
  122. file.Seek(0, 0) //seek to beginning
  123. ulMeta.Format = header.Header.Get("Content-type")
  124. ulMeta.Size = header.Size // necessary to prevent duplicate
  125. ulMeta.LastModified = 0
  126. ulMeta.Sha256 = checksum // necessary to prevent duplicate
  127. ulMeta.By = ss.User
  128. e = ulMeta.Write() // this Id will have the real Id if there is duplicates
  129. if e != nil {
  130. log.Error("Fail to update db ", ulMeta, e)
  131. } else {
  132. if (id > 0 && ulMeta.Id != id) || (id == 0 && ulMeta.IsDuplicate) {
  133. duplicate = true
  134. }
  135. ul := uploadsOnDisk{}
  136. ul.Upload = ulMeta
  137. e = os.Rename(filePath, ul.filePath())
  138. if e != nil {
  139. os.Remove(filePath)
  140. log.Error("fail to move file from ", filePath, "to", ul.filePath())
  141. }
  142. }
  143. return
  144. }
  145. func saveUploadToFile(r *http.Request) (filename string, e error) {
  146. e = r.ParseMultipartForm(10 << 20)
  147. if e != nil {
  148. return
  149. }
  150. file, header, e := r.FormFile("files")
  151. if e != nil {
  152. log.Println("Error Getting File", e)
  153. return
  154. }
  155. out, pathError := ioutil.TempFile(config.UploadsDir.FileDir, "can-del-upload-*.tmp")
  156. if pathError != nil {
  157. log.Println("Error Creating a file for writing", pathError)
  158. return
  159. }
  160. out.Seek(0, 0) //seek to beginning
  161. size, e := io.Copy(out, file)
  162. if e != nil {
  163. os.Remove(out.Name()) //remove on failure
  164. log.Println("Error copying", e)
  165. return
  166. }
  167. if size != header.Size {
  168. e = errors.New("written file with incorrect size")
  169. }
  170. return out.Name(), e
  171. }
  172. func getRequestedUpload(w http.ResponseWriter, r *http.Request, ss *loan.Session) (ret uploadsOnDisk, e error) {
  173. strId := r.URL.Path[len(apiV1Prefix+"upload-as-image/"):] //remove prefix
  174. Id, e := strconv.Atoi(strId)
  175. if e != nil {
  176. log.Error("Invalid uploads Id cannot convert to integer", Id, e)
  177. apiV1Client403Error(w, r, ss)
  178. return
  179. }
  180. ul := loan.Uploads{}
  181. e = ul.Read(int64(Id))
  182. if e != nil {
  183. log.Error("Upload not found or read error from db", Id, e)
  184. apiV1Client404Error(w, r, ss)
  185. return
  186. }
  187. ret.Upload = ul
  188. return
  189. }
  190. func apiV1UploadAsImage(w http.ResponseWriter, r *http.Request, ss *loan.Session) {
  191. ul, e := getRequestedUpload(w, r, ss)
  192. if e != nil {
  193. return
  194. }
  195. // if this is image itself, serve it directly
  196. if strings.Contains(strings.ToLower(ul.Upload.Format), "image") {
  197. f, e := os.Open(ul.filePath())
  198. if e == nil {
  199. defer f.Close()
  200. fi, e := f.Stat()
  201. if e == nil {
  202. w.Header().Set("Content-Disposition", "attachment; filename="+ul.Upload.FileName)
  203. http.ServeContent(w, r, ul.filePath(), fi.ModTime(), f)
  204. return
  205. }
  206. }
  207. // if we reach here, some err has happened
  208. log.Error("failed to serve image file ", ul, e)
  209. apiV1Server500Error(w, r)
  210. return
  211. }
  212. // see if a converted image exist, if not convert it and then send
  213. if !fileExists(ul.jpgPath()) {
  214. e = ul.convertUploadsToJpg()
  215. if e != nil {
  216. // serve a default no preview is available
  217. http.ServeFile(w, r, config.UploadsDir.JpgDefault)
  218. log.Error("error creating preview image", ul, e)
  219. return
  220. }
  221. }
  222. if fileExists(ul.jpgPath()) {
  223. http.ServeFile(w, r, ul.jpgPath())
  224. return
  225. } else {
  226. apiV1Client404Error(w, r, ss)
  227. }
  228. }
  229. func apiV1UploadAsThumbnail(w http.ResponseWriter, r *http.Request, ss *loan.Session) {
  230. ul, e := getRequestedUpload(w, r, ss)
  231. if e != nil {
  232. return
  233. }
  234. // see if a thumbnail is available already
  235. if !fileExists(ul.thumbPath()) {
  236. e = ul.convertUploadsToThumb()
  237. if e != nil {
  238. // serve a default no preview is available
  239. http.ServeFile(w, r, config.UploadsDir.ThumbDefault)
  240. log.Error("error creating preview image", ul, e)
  241. return
  242. }
  243. }
  244. if fileExists(ul.thumbPath()) {
  245. http.ServeFile(w, r, ul.thumbPath())
  246. return
  247. } else {
  248. apiV1Client404Error(w, r, ss)
  249. }
  250. }
  251. func apiV1UploadAPDF(w http.ResponseWriter, r *http.Request, ss *loan.Session) {
  252. ul, e := getRequestedUpload(w, r, ss)
  253. if e != nil {
  254. return
  255. }
  256. //get file type
  257. fileType, e := ul.GetFileType()
  258. if e != nil {
  259. apiV1Client403Error(w, r, ss)
  260. return
  261. }
  262. // if its ready pdf, no need to convert
  263. if fileType == "pdf" {
  264. f, e := os.Open(ul.filePath())
  265. if e == nil {
  266. defer f.Close()
  267. fi, e := f.Stat()
  268. if e == nil {
  269. w.Header().Set("Content-Disposition", "attachment; filename="+ul.Upload.FileName)
  270. http.ServeContent(w, r, ul.filePath(), fi.ModTime(), f)
  271. return
  272. }
  273. }
  274. // if we reach here, some err has happened
  275. log.Error("failed to serve pdf file ", ul, e)
  276. apiV1Server500Error(w, r)
  277. return
  278. }
  279. // see if a converted pdf exist, if not convert it and then send
  280. if !fileExists(ul.pdfPath()) {
  281. e = ul.convertUploadsToPDF()
  282. if e != nil {
  283. // serve a default no preview is available
  284. http.ServeFile(w, r, config.UploadsDir.PdfDefault)
  285. log.Error("error creating preview image", ul, e)
  286. return
  287. }
  288. }
  289. if fileExists(ul.pdfPath()) {
  290. http.ServeFile(w, r, ul.pdfPath())
  291. return
  292. } else {
  293. apiV1Client404Error(w, r, ss)
  294. }
  295. }