upload.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553
  1. package api
  2. import (
  3. "crypto/md5"
  4. "encoding/hex"
  5. "fmt"
  6. "image"
  7. "image/gif"
  8. "image/jpeg"
  9. "image/png"
  10. "io"
  11. "log"
  12. "mime/multipart"
  13. "net/http"
  14. "os"
  15. "path"
  16. "strconv"
  17. "strings"
  18. "github.com/pkg/errors"
  19. fs "github.com/axetroy/go-fs"
  20. "github.com/gin-gonic/gin"
  21. "github.com/nfnt/resize"
  22. "kpt.xdmy/apiserver/routers/restful"
  23. "kpt.xdmy/pkg/app"
  24. "kpt.xdmy/pkg/e"
  25. "kpt.xdmy/pkg/logging"
  26. "kpt.xdmy/pkg/setting"
  27. )
  28. // 支持的图片后缀名
  29. var supportImageExtNames = []string{".jpg", ".jpeg", ".png", ".ico", ".svg", ".bmp", ".gif"}
  30. /**
  31. check a file is a image or not
  32. */
  33. func isImage(extName string) bool {
  34. for i := 0; i < len(supportImageExtNames); i++ {
  35. if supportImageExtNames[i] == extName {
  36. return true
  37. }
  38. }
  39. return false
  40. }
  41. /**
  42. Handler the parse error
  43. */
  44. func parseFormFail(context *gin.Context) {
  45. context.JSON(http.StatusBadRequest, gin.H{
  46. "message": "Can not parse form",
  47. })
  48. }
  49. /**
  50. Upload file handler
  51. */
  52. func UploadFile(context *gin.Context) {
  53. appG := app.Gin{C: context}
  54. dictId := context.Param("id")
  55. dictName := context.Param("name")
  56. logging.Info("UploadFile ", context.Keys, dictId, dictName)
  57. var (
  58. isSupportFile bool
  59. maxUploadSize = setting.AppSetting.FileMaxSize // 最大上传大小
  60. allowTypes = setting.AppSetting.FileAllowType // 可上传的文件类型
  61. distPath string // 最终的输出目录
  62. err error
  63. file *multipart.FileHeader
  64. src multipart.File
  65. dist *os.File
  66. )
  67. // Source
  68. if file, err = context.FormFile("file"); err != nil {
  69. parseFormFail(context)
  70. return
  71. }
  72. sqlname := context.GetHeader("optname")
  73. extname := path.Ext(file.Filename)
  74. if len(allowTypes) != 0 {
  75. for i := 0; i < len(allowTypes); i++ {
  76. if allowTypes[i] == extname {
  77. isSupportFile = true
  78. break
  79. }
  80. }
  81. if isSupportFile == false {
  82. context.JSON(http.StatusBadRequest, gin.H{
  83. "message": "不支持的文件类型: " + extname,
  84. })
  85. return
  86. }
  87. }
  88. if file.Size > int64(maxUploadSize) {
  89. context.JSON(http.StatusBadRequest, gin.H{
  90. "message": "上传文件太大, 最大限制为" + strconv.Itoa(int(maxUploadSize)/1048576) + "(M): ",
  91. })
  92. return
  93. }
  94. if src, err = file.Open(); err != nil {
  95. // open the file fail...
  96. }
  97. defer src.Close()
  98. hash := md5.New()
  99. io.Copy(hash, src)
  100. md5string := hex.EncodeToString(hash.Sum([]byte("")))
  101. fileName := md5string + extname
  102. // Destination
  103. filePath := setting.CurrentPath + setting.AppSetting.FileSavePath + dictName + "/"
  104. err = PathCheck(filePath) //检查路径并创建
  105. if err != nil {
  106. fmt.Println("PathCheck err", err)
  107. }
  108. distPath = path.Join(filePath, fileName)
  109. if dist, err = os.Create(distPath); err != nil {
  110. fmt.Println("Create err", err)
  111. }
  112. defer dist.Close()
  113. //distPath = setting.CurrentPath + setting.AppSetting.FileSavePath +"/"+ fileName
  114. if dist, err = os.Create(distPath); err != nil {
  115. // create dist file fail...
  116. }
  117. defer dist.Close()
  118. // FIXME: open 2 times
  119. if src, err = file.Open(); err != nil {
  120. //
  121. }
  122. // Copy
  123. io.Copy(dist, src)
  124. var execresult interface{}
  125. params := context.Request.Form
  126. if sqlname != "" {
  127. sql, p := restful.GetSqlByNameDB(sqlname) //todo insertcustomdoc
  128. if sql != "" {
  129. s_params := make([]interface{}, 0)
  130. paramslist := strings.Split(p, ",")
  131. if len(paramslist) > 0 && p != "" {
  132. for _, value := range paramslist {
  133. fmt.Println("s_params value", s_params, value)
  134. if strings.ToLower(strings.Trim(value, " ")) == "username" { //picpath, picname, username, newpicname
  135. tempv := params.Get("jwt_username")
  136. s_params = append(s_params, tempv)
  137. } else if strings.ToLower(strings.Trim(value, " ")) == "docname" {
  138. s_params = append(s_params, file.Filename)
  139. } else if strings.ToLower(strings.Trim(value, " ")) == "newdocname" {
  140. s_params = append(s_params, fileName)
  141. } else if strings.ToLower(strings.Trim(value, " ")) == "docpath" {
  142. s_params = append(s_params, dictName) //
  143. } else if strings.ToLower(strings.Trim(value, " ")) == "dictid" {
  144. s_params = append(s_params, dictId) //
  145. fmt.Println("s_params", s_params, dictId)
  146. } else if strings.ToLower(strings.Trim(value, " ")) == "filesize" {
  147. s_params = append(s_params, file.Size) //
  148. } else {
  149. s_params = append(s_params, params.Get(strings.Trim(value, " ")))
  150. }
  151. }
  152. }
  153. execresult, err = execDataBySql(sql, s_params)
  154. if err != nil {
  155. fmt.Println("execDataBySql err", err)
  156. appG.Response(http.StatusOK, e.ERROR, err.Error())
  157. }
  158. }
  159. }
  160. context.JSON(http.StatusOK, gin.H{
  161. "hash": md5string,
  162. "filename": fileName,
  163. "origin": file.Filename,
  164. "size": file.Size,
  165. "execresult": execresult,
  166. })
  167. }
  168. /**
  169. Upload image handler
  170. */
  171. func UploaderImage(context *gin.Context) {
  172. logging.Info("UploaderImage ", context.Keys)
  173. var (
  174. maxUploadSize = setting.AppSetting.ImageMaxSize // 最大上传大小
  175. distPath string // 最终的输出目录
  176. err error
  177. file *multipart.FileHeader
  178. src multipart.File
  179. dist *os.File
  180. )
  181. // Source
  182. if file, err = context.FormFile("file"); err != nil {
  183. parseFormFail(context)
  184. return
  185. }
  186. sqlname := context.GetHeader("optname")
  187. extname := strings.ToLower(path.Ext(file.Filename))
  188. if isImage(extname) == false {
  189. context.JSON(http.StatusBadRequest, gin.H{
  190. "message": "不支持的上传文件类型: " + extname,
  191. })
  192. return
  193. }
  194. if file.Size > int64(maxUploadSize) {
  195. context.JSON(http.StatusBadRequest, gin.H{
  196. "message": "上传文件太大, 最大文件大小限制为(byte): " + strconv.Itoa(int(maxUploadSize)),
  197. })
  198. return
  199. }
  200. if src, err = file.Open(); err != nil {
  201. }
  202. defer src.Close()
  203. hash := md5.New()
  204. io.Copy(hash, src)
  205. md5string := hex.EncodeToString(hash.Sum([]byte("")))
  206. fileName := md5string + extname
  207. picPath := setting.CurrentPath + setting.AppSetting.ImageSavePath + sqlname + "/"
  208. err = PathCheck(picPath) //检查路径并创建
  209. if err != nil {
  210. fmt.Println("PathCheck err", err)
  211. }
  212. distPath = path.Join(picPath, fileName)
  213. if dist, err = os.Create(distPath); err != nil {
  214. fmt.Println("Create err", err)
  215. }
  216. defer dist.Close()
  217. // FIXME: open 2 times
  218. if src, err = file.Open(); err != nil {
  219. //
  220. }
  221. defer src.Close()
  222. // Copy
  223. io.Copy(dist, src)
  224. // 压缩缩略图
  225. // 不管成功与否,都会进行下一步的返回
  226. if _, err := thumbnailify(distPath, sqlname); err != nil {
  227. logging.Error("thumbnailify_err", err)
  228. picThumbnailPath := setting.CurrentPath + setting.AppSetting.ThumbnailSavePath + sqlname + "/"
  229. println(picThumbnailPath)
  230. err = PathCheck(picThumbnailPath) //检查路径并创建
  231. distThumbnailPath := path.Join(picThumbnailPath, fileName)
  232. println(distThumbnailPath)
  233. distThumbnail, err := os.Create(distThumbnailPath)
  234. if err != nil {
  235. fmt.Println("CreateThumbnail err", err)
  236. }
  237. srcThumbnail, err := file.Open()
  238. if err != nil {
  239. //
  240. }
  241. io.Copy(distThumbnail, srcThumbnail)
  242. distThumbnail.Close()
  243. src.Close()
  244. }
  245. var execresult interface{}
  246. params := context.Request.Form
  247. if sqlname != "" {
  248. sql, p := restful.GetSqlByNameDB(sqlname)
  249. if sql != "" {
  250. s_params := make([]interface{}, 0)
  251. paramslist := strings.Split(p, ",")
  252. if len(paramslist) > 0 && p != "" {
  253. for _, value := range paramslist {
  254. if strings.ToLower(strings.Trim(value, " ")) == "username" { //picpath, picname, username, newpicname
  255. tempv := params.Get("jwt_username")
  256. s_params = append(s_params, tempv)
  257. } else if strings.ToLower(strings.Trim(value, " ")) == "picname" {
  258. s_params = append(s_params, file.Filename)
  259. } else if strings.ToLower(strings.Trim(value, " ")) == "newpicname" {
  260. s_params = append(s_params, fileName)
  261. } else if strings.ToLower(strings.Trim(value, " ")) == "picpath" {
  262. s_params = append(s_params, sqlname) //全路径加文件名
  263. } else {
  264. s_params = append(s_params, params.Get(strings.Trim(value, " ")))
  265. }
  266. }
  267. }
  268. execresult, err = execDataBySql(sql, s_params)
  269. if err != nil {
  270. fmt.Println("execDataBySql err", err)
  271. }
  272. }
  273. }
  274. context.JSON(http.StatusOK, gin.H{
  275. "hash": md5string,
  276. "filename": fileName,
  277. "origin": file.Filename,
  278. "size": file.Size,
  279. "execresult": execresult,
  280. })
  281. }
  282. /**
  283. Get file raw
  284. */
  285. func GetFileRaw(context *gin.Context) {
  286. filename := context.Param("filename")
  287. logging.Info("GetFileRaw ", context.Keys, filename)
  288. filePath := path.Join(setting.CurrentPath, setting.AppSetting.FileSavePath, filename)
  289. if isExistFile := fs.PathExists(filePath); isExistFile == false {
  290. // if the path not found
  291. http.NotFound(context.Writer, context.Request)
  292. return
  293. }
  294. http.ServeFile(context.Writer, context.Request, filePath)
  295. }
  296. /**
  297. Download a file
  298. */
  299. func DownloadFile(context *gin.Context) {
  300. filename := context.Param("filename")
  301. logging.Info("DownloadFile ", context.Keys, filename)
  302. sqlstr := fmt.Sprintf("SELECT docpath ,newdocname FROM eq_doc where id = %s ", filename)
  303. var docpath, newdocname string
  304. err := restful.BasicList(sqlstr, nil, &docpath, &newdocname)
  305. if err != nil {
  306. log.Default().Printf("DownloadFile queryx:%v", err)
  307. }
  308. originFilePath := path.Join(setting.CurrentPath, setting.AppSetting.FileSavePath, docpath, newdocname)
  309. if fs.PathExists(originFilePath) == false {
  310. http.NotFound(context.Writer, context.Request)
  311. return
  312. }
  313. http.ServeFile(context.Writer, context.Request, originFilePath)
  314. }
  315. /**
  316. Get Origin image
  317. */
  318. func GetOriginImage(context *gin.Context) {
  319. //appG := app.Gin{C: context}
  320. filename := context.Param("filename")
  321. logging.Info("GetOriginImage ", context.Keys, filename)
  322. sqlstr := fmt.Sprintf("SELECT picpath,newpicname FROM eq_pic where id = %s ", filename)
  323. var picpath, newpicname string
  324. err := restful.BasicList(sqlstr, nil, &picpath, &newpicname)
  325. if err != nil {
  326. log.Default().Printf("GetOriginImage queryx eq_pic: %v", err)
  327. }
  328. if picpath == "" && newpicname == "" {
  329. http.NotFound(context.Writer, context.Request)
  330. return
  331. }
  332. originImagePath := path.Join(setting.CurrentPath, setting.AppSetting.ImageSavePath, picpath, newpicname)
  333. if fs.PathExists(originImagePath) == false {
  334. // if the path not found
  335. http.NotFound(context.Writer, context.Request)
  336. return
  337. }
  338. http.ServeFile(context.Writer, context.Request, originImagePath)
  339. //appG.Response(http.StatusOK, e.SUCCESS, eqpic[0]["picname"])
  340. }
  341. /**
  342. Get thumbnail image
  343. */
  344. func GetThumbnailImage(context *gin.Context) {
  345. filename := context.Param("filename")
  346. logging.Info("GetThumbnailImage ", context.Keys, filename)
  347. sqlstr := fmt.Sprintf("SELECT picpath,newpicname FROM eq_pic where id = %s ", filename)
  348. var picpath, newpicname string
  349. err := restful.BasicList(sqlstr, nil, &picpath, &newpicname)
  350. if err != nil {
  351. log.Default().Printf("GetOriginImage queryx eq_pic: %v", err)
  352. }
  353. if newpicname == "" {
  354. http.NotFound(context.Writer, context.Request)
  355. return
  356. }
  357. thumbnailImagePath := path.Join(setting.CurrentPath, setting.AppSetting.ThumbnailSavePath, picpath, newpicname)
  358. originImagePath := path.Join(setting.CurrentPath, setting.AppSetting.ImageSavePath, filename)
  359. if fs.PathExists(thumbnailImagePath) == false {
  360. // if thumbnail image not exist, try to get origin image
  361. if fs.PathExists(originImagePath) == true {
  362. http.ServeFile(context.Writer, context.Request, originImagePath)
  363. return
  364. }
  365. // if the path not found
  366. http.NotFound(context.Writer, context.Request)
  367. return
  368. }
  369. http.ServeFile(context.Writer, context.Request, thumbnailImagePath)
  370. }
  371. /**
  372. Generate thumbnail
  373. */
  374. func thumbnailify(imagePath, subdirectory string) (outputPath string, err error) {
  375. var (
  376. file *os.File
  377. img image.Image
  378. )
  379. Filename := strings.ToLower(path.Base(imagePath))
  380. extname := strings.ToLower(path.Ext(imagePath))
  381. outputPath = setting.CurrentPath + setting.AppSetting.ThumbnailSavePath + subdirectory + "/" + Filename
  382. err = PathCheck(setting.CurrentPath + setting.AppSetting.ThumbnailSavePath + subdirectory)
  383. if err != nil {
  384. fmt.Println("thumbnailify PathCheck err", err)
  385. }
  386. // 读取文件
  387. if file, err = os.Open(imagePath); err != nil {
  388. return
  389. }
  390. defer file.Close()
  391. // decode jpeg into image.Image
  392. switch extname {
  393. case ".jpg", ".jpeg":
  394. img, err = jpeg.Decode(file)
  395. break
  396. case ".png":
  397. img, err = png.Decode(file)
  398. break
  399. case ".gif":
  400. img, err = gif.Decode(file)
  401. break
  402. default:
  403. err = errors.New("Unsupport file type" + extname)
  404. return
  405. }
  406. if img == nil {
  407. err = errors.New("Generate thumbnail fail...")
  408. return
  409. }
  410. m := resize.Thumbnail(uint(setting.AppSetting.ThumbnailMaxWidth), uint(setting.AppSetting.ThumbnailMaxHeight), img, resize.Lanczos3)
  411. out, err := os.Create(outputPath)
  412. if err != nil {
  413. return
  414. }
  415. defer out.Close()
  416. // write new image to file
  417. //decode jpeg/png/gif into image.Image
  418. switch extname {
  419. case ".jpg", ".jpeg":
  420. jpeg.Encode(out, m, nil)
  421. break
  422. case ".png":
  423. png.Encode(out, m)
  424. break
  425. case ".gif":
  426. gif.Encode(out, m, nil)
  427. break
  428. default:
  429. err = errors.New("Unsupport file type" + extname)
  430. return
  431. }
  432. return
  433. }
  434. func UploadFiles(c *gin.Context) {
  435. logging.Info("UploadFiles ", c.Keys)
  436. appG := app.Gin{C: c}
  437. err := c.Request.ParseMultipartForm(200000)
  438. if err != nil {
  439. appG.Response(http.StatusOK, e.ERROR_IMPORT_FAIL, err)
  440. return
  441. }
  442. // 获取表单
  443. form := c.Request.MultipartForm
  444. // 获取参数upload后面的多个文件名,存放到数组files里面,
  445. files := form.File["upload"]
  446. // 遍历数组,每取出一个file就拷贝一次
  447. for i := range files {
  448. file, err := files[i].Open()
  449. defer file.Close()
  450. if err != nil {
  451. appG.Response(http.StatusOK, e.ERROR_IMPORT_FAIL, err)
  452. return
  453. }
  454. fileName := files[i].Filename
  455. fmt.Println(fileName)
  456. out, err := os.Create(fileName)
  457. defer out.Close()
  458. if err != nil {
  459. appG.Response(http.StatusOK, e.ERROR_IMPORT_FAIL, err)
  460. return
  461. }
  462. _, err = io.Copy(out, file)
  463. if err != nil {
  464. appG.Response(http.StatusOK, e.ERROR_IMPORT_FAIL, err)
  465. return
  466. }
  467. appG.Response(http.StatusOK, e.SUCCESS, "upload successful \n")
  468. }
  469. }
  470. func PathCheck(path string) (err error) {
  471. b, err := PathExists(path)
  472. if err != nil {
  473. fmt.Println("exist err", err)
  474. }
  475. if !b {
  476. fmt.Println(path, " 目录不存在,重新创建")
  477. err = os.Mkdir(path, 0777)
  478. if err != nil {
  479. fmt.Println("Mkdir err", err)
  480. }
  481. }
  482. return
  483. }
  484. func PathExists(path string) (bool, error) {
  485. _, err := os.Stat(path)
  486. if err == nil {
  487. return true, nil
  488. }
  489. if os.IsNotExist(err) {
  490. return false, nil
  491. }
  492. return false, err
  493. }