package api import ( "crypto/md5" "encoding/hex" "errors" "fmt" "github.com/axetroy/go-fs" "github.com/gin-gonic/gin" "../../pkg/app" "../../pkg/e" "../../pkg/logging" "../../pkg/setting" "../../routers/restful" "github.com/nfnt/resize" "image" "image/gif" "image/jpeg" "image/png" "io" "mime/multipart" "net/http" "os" "path" "strconv" "strings" ) // 支持的图片后缀名 var supportImageExtNames = []string{".jpg", ".jpeg", ".png", ".ico", ".svg", ".bmp", ".gif"} /** check a file is a image or not */ func isImage(extName string) bool { for i := 0; i < len(supportImageExtNames); i++ { if supportImageExtNames[i] == extName { return true } } return false } /** Handler the parse error */ func parseFormFail(context *gin.Context) { context.JSON(http.StatusBadRequest, gin.H{ "message": "Can not parse form", }) } /** Upload file handler */ func UploadFile(context *gin.Context) { appG := app.Gin{C: context} dictId := context.Param("id") dictName := context.Param("name") logging.Info("UploadFile ",context.Keys,dictId,dictName) var ( isSupportFile bool maxUploadSize = setting.AppSetting.FileMaxSize // 最大上传大小 allowTypes = setting.AppSetting.FileAllowType // 可上传的文件类型 distPath string // 最终的输出目录 err error file *multipart.FileHeader src multipart.File dist *os.File ) // Source if file, err = context.FormFile("file"); err != nil { parseFormFail(context) return } sqlname := context.GetHeader("optname") extname := path.Ext(file.Filename) if len(allowTypes) != 0 { for i := 0; i < len(allowTypes); i++ { if allowTypes[i] == extname { isSupportFile = true break } } if isSupportFile == false { context.JSON(http.StatusBadRequest, gin.H{ "message": "不支持的文件类型: " + extname, }) return } } if file.Size > int64(maxUploadSize) { context.JSON(http.StatusBadRequest, gin.H{ "message": "上传文件太大, 最大限制为(byte): " + strconv.Itoa(int(maxUploadSize)), }) return } if src, err = file.Open(); err != nil { // open the file fail... } defer src.Close() hash := md5.New() io.Copy(hash, src) md5string := hex.EncodeToString(hash.Sum([]byte(""))) fileName := md5string + extname // Destination filePath := setting.CurrentPath+setting.AppSetting.FileSavePath+dictName+"/" err = PathCheck(filePath) //检查路径并创建 if err != nil { fmt.Println("PathCheck err",err) } distPath = path.Join(filePath, fileName) if dist, err = os.Create(distPath); err != nil { fmt.Println("Create err",err) } defer dist.Close() //distPath = setting.CurrentPath + setting.AppSetting.FileSavePath +"/"+ fileName if dist, err = os.Create(distPath); err != nil { // create dist file fail... } defer dist.Close() // FIXME: open 2 times if src, err = file.Open(); err != nil { // } // Copy io.Copy(dist, src) var execresult interface{} params := context.Request.Form if sqlname != "" { sql, p := restful.GetSqlByNameDB(sqlname)//todo insertcustomdoc if sql != ""{ s_params := make([]interface{}, 0) paramslist := strings.Split(p,",") if len(paramslist)>0 && p!="" { for _, value := range paramslist { fmt.Println("s_params value",s_params,value) if (strings.ToLower(strings.Trim(value," "))=="username"){//picpath, picname, username, newpicname tempv := params.Get("jwt_username") s_params = append(s_params, tempv) }else if (strings.ToLower(strings.Trim(value," "))=="docname"){ s_params = append(s_params, file.Filename) }else if (strings.ToLower(strings.Trim(value," "))=="newdocname"){ s_params = append(s_params, fileName) }else if (strings.ToLower(strings.Trim(value," "))=="docpath"){ s_params = append(s_params, dictName) // }else if (strings.ToLower(strings.Trim(value," "))=="dictid"){ s_params = append(s_params,dictId) // fmt.Println("s_params",s_params,dictId) }else if (strings.ToLower(strings.Trim(value," "))=="filesize"){ s_params = append(s_params, file.Size) // }else{ s_params = append(s_params, params.Get(strings.Trim(value," "))) } } } execresult, err = execDataBySql(sql, s_params) if err != nil{ fmt.Println("execDataBySql err",err) appG.Response(http.StatusOK, e.ERROR, err.Error()) } } } context.JSON(http.StatusOK, gin.H{ "hash": md5string, "filename": fileName, "origin": file.Filename, "size": file.Size, "execresult": execresult, }) } /** Upload image handler */ func UploaderImage(context *gin.Context) { logging.Info("UploaderImage ",context.Keys) var ( maxUploadSize = setting.AppSetting.ImageMaxSize // 最大上传大小 distPath string // 最终的输出目录 err error file *multipart.FileHeader src multipart.File dist *os.File ) // Source if file, err = context.FormFile("file"); err != nil { parseFormFail(context) return } sqlname := context.GetHeader("optname") extname := strings.ToLower(path.Ext(file.Filename)) if isImage(extname) == false { context.JSON(http.StatusBadRequest, gin.H{ "message": "不支持的上传文件类型: " + extname, }) return } if file.Size > int64(maxUploadSize) { context.JSON(http.StatusBadRequest, gin.H{ "message": "上传文件太大, 最大文件大小限制为(byte): " + strconv.Itoa(int(maxUploadSize)), }) return } if src, err = file.Open(); err != nil { } defer src.Close() hash := md5.New() io.Copy(hash, src) md5string := hex.EncodeToString(hash.Sum([]byte(""))) fileName := md5string + extname //savePathDir := setting.CurrentPath+setting.AppSetting.ImageSavePath+fileName+"/" //_,err = os.Stat(savePathDir) //if err == nil { // fmt.Println(err)//todo 错误处理 //} //if os.IsNotExist(err) { // err:=os.Mkdir(setting.CurrentPath+setting.AppSetting.ImageSavePath+fileName,os.ModePerm) // if err!=nil{ // fmt.Println(err) // }//目录不存在则创建 //} // Destination picPath := setting.CurrentPath+setting.AppSetting.ImageSavePath+sqlname+"/" err = PathCheck(picPath) //检查路径并创建 if err != nil { fmt.Println("PathCheck err",err) } distPath = path.Join(picPath, fileName) if dist, err = os.Create(distPath); err != nil { fmt.Println("Create err",err) } defer dist.Close() // FIXME: open 2 times if src, err = file.Open(); err != nil { // } defer src.Close() // Copy io.Copy(dist, src) // 压缩缩略图 // 不管成功与否,都会进行下一步的返回 if _, err := thumbnailify(distPath,sqlname); err != nil { logging.Error("thumbnailify_err",err) picThumbnailPath := setting.CurrentPath+setting.AppSetting.ThumbnailSavePath+sqlname+"/" println(picThumbnailPath) err = PathCheck(picThumbnailPath) //检查路径并创建 distThumbnailPath := path.Join(picThumbnailPath, fileName) println(distThumbnailPath) distThumbnail, err := os.Create(distThumbnailPath) if err != nil { fmt.Println("CreateThumbnail err",err) } srcThumbnail, err := file.Open() if err != nil { // } io.Copy(distThumbnail, srcThumbnail) distThumbnail.Close() src.Close() } var execresult interface{} params := context.Request.Form if sqlname != "" { sql, p := restful.GetSqlByNameDB(sqlname) if sql != ""{ s_params := make([]interface{}, 0) paramslist := strings.Split(p,",") if len(paramslist)>0 && p!="" { for _, value := range paramslist { if (strings.ToLower(strings.Trim(value," "))=="username"){//picpath, picname, username, newpicname tempv := params.Get("jwt_username") s_params = append(s_params, tempv) }else if (strings.ToLower(strings.Trim(value," "))=="picname"){ s_params = append(s_params, file.Filename) }else if (strings.ToLower(strings.Trim(value," "))=="newpicname"){ s_params = append(s_params, fileName) }else if (strings.ToLower(strings.Trim(value," "))=="picpath"){ s_params = append(s_params, sqlname) //全路径加文件名 } else{ s_params = append(s_params, params.Get(strings.Trim(value," "))) } } } execresult, err = execDataBySql(sql, s_params) if err != nil{ fmt.Println("execDataBySql err",err) } } } context.JSON(http.StatusOK, gin.H{ "hash": md5string, "filename": fileName, "origin": file.Filename, "size": file.Size, "execresult": execresult, }) } /** Get file raw */ func GetFileRaw(context *gin.Context) { filename := context.Param("filename") logging.Info("GetFileRaw ",context.Keys,filename) filePath := path.Join(setting.CurrentPath, setting.AppSetting.FileSavePath, filename) if isExistFile := fs.PathExists(filePath); isExistFile == false { // if the path not found http.NotFound(context.Writer, context.Request) return } http.ServeFile(context.Writer, context.Request, filePath) } /** Download a file */ func DownloadFile(context *gin.Context) { filename := context.Param("filename") logging.Info("DownloadFile ",context.Keys,filename) eqpic, _ := restful.Engine.SQL("SELECT * FROM eq_doc where id = ? ", filename).QueryString() if eqpic == nil { http.NotFound(context.Writer, context.Request) return } originFilePath := path.Join(setting.CurrentPath, setting.AppSetting.FileSavePath,eqpic[0]["docpath"],eqpic[0]["newdocname"]) if fs.PathExists(originFilePath) == false { // if the path not found http.NotFound(context.Writer, context.Request) return } http.ServeFile(context.Writer, context.Request, originFilePath) } /** Get Origin image */ func GetOriginImage(context *gin.Context) { //appG := app.Gin{C: context} filename := context.Param("filename") logging.Info("GetOriginImage ",context.Keys,filename) eqpic, _ := restful.Engine.SQL("SELECT * FROM eq_pic where id = ? ", filename).QueryString() if eqpic == nil { http.NotFound(context.Writer, context.Request) return } originImagePath := path.Join(setting.CurrentPath, setting.AppSetting.ImageSavePath,eqpic[0]["picpath"],eqpic[0]["newpicname"]) if fs.PathExists(originImagePath) == false { // if the path not found http.NotFound(context.Writer, context.Request) return } http.ServeFile(context.Writer, context.Request, originImagePath) //appG.Response(http.StatusOK, e.SUCCESS, eqpic[0]["picname"]) } /** Get thumbnail image */ func GetThumbnailImage(context *gin.Context) { filename := context.Param("filename") logging.Info("GetThumbnailImage ",context.Keys,filename) eqpic, _ := restful.Engine.SQL("SELECT * FROM eq_pic where id = ? ", filename).QueryString() if eqpic == nil { http.NotFound(context.Writer, context.Request) return } thumbnailImagePath := path.Join(setting.CurrentPath, setting.AppSetting.ThumbnailSavePath,eqpic[0]["picpath"],eqpic[0]["newpicname"]) originImagePath := path.Join(setting.CurrentPath, setting.AppSetting.ImageSavePath, filename) if fs.PathExists(thumbnailImagePath) == false { // if thumbnail image not exist, try to get origin image if fs.PathExists(originImagePath) == true { http.ServeFile(context.Writer, context.Request, originImagePath) return } // if the path not found http.NotFound(context.Writer, context.Request) return } http.ServeFile(context.Writer, context.Request, thumbnailImagePath) } /** Generate thumbnail */ func thumbnailify(imagePath,subdirectory string) (outputPath string, err error) { var ( file *os.File img image.Image ) Filename := strings.ToLower(path.Base(imagePath)) extname := strings.ToLower(path.Ext(imagePath)) outputPath = setting.CurrentPath + setting.AppSetting.ThumbnailSavePath +subdirectory+ "/" + Filename err = PathCheck(setting.CurrentPath + setting.AppSetting.ThumbnailSavePath +subdirectory) if err !=nil{ fmt.Println("thumbnailify PathCheck err",err) } // 读取文件 if file, err = os.Open(imagePath); err != nil { return } defer file.Close() // decode jpeg into image.Image switch extname { case ".jpg", ".jpeg": img, err = jpeg.Decode(file) break case ".png": img, err = png.Decode(file) break case ".gif": img, err = gif.Decode(file) break default: err = errors.New("Unsupport file type" + extname) return } if img == nil { err = errors.New("Generate thumbnail fail...") return } m := resize.Thumbnail(uint( setting.AppSetting.ThumbnailMaxWidth), uint(setting.AppSetting.ThumbnailMaxHeight), img, resize.Lanczos3) out, err := os.Create(outputPath) if err != nil { return } defer out.Close() // write new image to file //decode jpeg/png/gif into image.Image switch extname { case ".jpg", ".jpeg": jpeg.Encode(out, m, nil) break case ".png": png.Encode(out, m) break case ".gif": gif.Encode(out, m, nil) break default: err = errors.New("Unsupport file type" + extname) return } return } func UploadFiles(c *gin.Context) { logging.Info("UploadFiles ",c.Keys) appG := app.Gin{C: c} err := c.Request.ParseMultipartForm(200000) if err != nil { appG.Response(http.StatusOK, e.ERROR_IMPORT_FAIL, err) return } // 获取表单 form := c.Request.MultipartForm // 获取参数upload后面的多个文件名,存放到数组files里面, files := form.File["upload"] // 遍历数组,每取出一个file就拷贝一次 for i, _ := range files { file, err := files[i].Open() defer file.Close() if err != nil { appG.Response(http.StatusOK, e.ERROR_IMPORT_FAIL, err) return } fileName := files[i].Filename fmt.Println(fileName) out, err := os.Create(fileName) defer out.Close() if err != nil { appG.Response(http.StatusOK, e.ERROR_IMPORT_FAIL, err) return } _, err = io.Copy(out, file) if err != nil { appG.Response(http.StatusOK, e.ERROR_IMPORT_FAIL, err) return } appG.Response(http.StatusOK, e.SUCCESS, "upload successful \n") } } func PathCheck(path string)(err error){ b,err :=PathExists(path) if err != nil { fmt.Println("exist err",err) } if !b{ fmt.Println(path," 目录不存在,重新创建") err = os.Mkdir(path, 0777) if err != nil { fmt.Println("Mkdir err",err) } } return } func PathExists(path string) (bool, error) { _, err := os.Stat(path) if err == nil { return true, nil } if os.IsNotExist(err) { return false, nil } return false, err }