package partial import ( "crypto/sha1" "fmt" "github.com/gin-gonic/gin" "github.com/pkg/errors" "io" "io/ioutil" "mime" "mime/multipart" "os" "path" "strconv" "time" "git.qianqiusoft.com/qianqiusoft/light-apiengine/entitys" syslogs "git.qianqiusoft.com/qianqiusoft/light-apiengine/logs" sysmodel "git.qianqiusoft.com/qianqiusoft/light-apiengine/models" sysutils "git.qianqiusoft.com/qianqiusoft/light-apiengine/utils" ) /** * 附件上传/下载接口 */ type AttachementUpDownloader interface { /** * @brief: 附件上传接口 * @param1 file: post 多媒体file * @param2 fileHeader: 文件相关头部信息 * @return1: 附件信息,主要包括id,url, hash和大小。其他字段会自动设置 * @return4: 错误信息 */ Upload(multipart.File, *multipart.FileHeader)(*sysmodel.SysAttachment, error) /** * @brief: 附件下载 * @param1 ctx: 上下文 * @param2 attach: 福建对象 */ Download(*entitys.CtrlContext, *sysmodel.SysAttachment) } // 附件上传下载接口 var _attachementUpDownloader AttachementUpDownloader = &defaultAttachUpDownloader{} /** * @brief: 设置附件上传下载接口 * @param1 uder: 上传下载接口 */ func SetAttachementUpDownloader(uder AttachementUpDownloader){ if uder != nil{ _attachementUpDownloader = uder } } // _Upload // @Title _Upload // @Description 上传文件 // @Success 200 {object} Account // @Failure 403 :id is empty func SysAttachment_Upload(c *entitys.CtrlContext) { attach, err := doUpload2(c) if err == nil { c.Ctx.JSON(200, sysmodel.SysReturn{200, "", attach.Id}) syslogs.Debug("上传附件成功:", attach.Name, attach.Size) } else { c.Ctx.JSON(500, sysmodel.SysReturn{500, err.Error(), nil}) } } // _Download // @Title _Download // @Description 下载文件 // @Param id string false "文件ID" // @Success 200 {object} Account // @Failure 403 :id is empty func SysAttachment_Download(c *entitys.CtrlContext) { attachId := c.Ctx.Query("id") var engine = c.PlatformDbEngine var attach sysmodel.SysAttachment has, err := engine.ID(attachId).Get(&attach) if err != nil || !has { syslogs.Error("获取附件出错了:", err) c.Ctx.JSON(500, sysmodel.SysReturn{500, "获取附件出错了", nil}) return } if _attachementUpDownloader != nil{ _attachementUpDownloader.Download(c, &attach) }else{ c.Ctx.JSON(500, gin.H{"code": 500, "msg": "附件上传下载接口为nil", "data": nil}) } } // _Delete // @Title _Delete // @Description 删除文件 // @Param id string false "文件ID" // @Success 200 {object} Account // @Failure 403 :id is empty func SysAttachment_Delete(c *entitys.CtrlContext) { attrId := c.Ctx.Query("id") attach := &sysmodel.SysAttachment{} attach.Id = attrId _, err := c.PlatformDbEngine.ID(attrId).Delete(attach) if err != nil { syslogs.Error("删除附件出错了:", err) c.Ctx.JSON(500, sysmodel.SysReturn{500, err.Error(), nil}) return } syslogs.Debug("删除附件:", attrId) c.Ctx.JSON(200, sysmodel.SysReturn{200, "", attrId}) } // _Get // @Title _Get // @Description 获取附件信息 // @Param id string false "附件id" // @Success 200 {object} Account // @Failure 403 :id is empty func SysAttachment_Get(c *entitys.CtrlContext) { var id = c.Ctx.Query("id") var attach sysmodel.SysAttachment has, err := c.PlatformDbEngine.ID(id).Get(&attach) if err == nil { if has { c.Ctx.JSON(200, sysmodel.SysReturn{200, "", attach}) } else { c.Ctx.JSON(200, sysmodel.SysReturn{500, "附件不存在", nil}) } } else { c.Ctx.JSON(200, sysmodel.SysReturn{500, err.Error(), nil}) } } func doUpload(c *entitys.CtrlContext) (*sysmodel.SysAttachment, error) { file, fInfo, err := c.Ctx.Request.FormFile("file") if err != nil { syslogs.Error("上传出错了:", err) return nil, err } download, hash, length, err := sysutils.PostFile(file) if err != nil { return nil, err } userId := c.Ctx.GetString("user_id") attach := &sysmodel.SysAttachment{} attach.Id = sysutils.NewUUID() attach.Name = fInfo.Filename attach.Size = length attach.Url = download attach.CreateBy = userId attach.CreateTime = time.Now() attach.Ext = path.Ext(attach.Name) attach.Hash = hash _, err = c.Db.InsertOne(attach) if err != nil { syslogs.Error("保存附件出错了:", err) return nil, err } return attach, nil } func doUpload2(c *entitys.CtrlContext) (*sysmodel.SysAttachment, error) { file, fInfo, err := c.Ctx.Request.FormFile("file") if err != nil { syslogs.Error("上传出错了:", err) return nil, err } defer file.Close() var attach *sysmodel.SysAttachment = nil if _attachementUpDownloader != nil{ attach, err = _attachementUpDownloader.Upload(file, fInfo) if err !=nil{ return nil, err } }else{ return nil, errors.New("附件上传下载接口为nil") } userId := c.Ctx.GetString("user_id") if attach.Id == ""{ attach.Id = sysutils.NewUUID() } if attach.Size <= 0{ attach.Size = int32((fInfo.Size)) } attach.Name = fInfo.Filename attach.CreateBy = userId attach.CreateTime = time.Now() attach.Ext = path.Ext(attach.Name) _, err = c.PlatformDbEngine.InsertOne(attach) if err != nil { syslogs.Error("保存附件出错了:", err) return nil, err } return attach, nil } func mkdir(dir string) error { _, err := os.Stat(dir) if err != nil { err = os.MkdirAll(dir, os.ModePerm) } return err } func FileHasH(filePath string) string { bytes, err := ioutil.ReadFile(filePath) if err == nil && len(bytes) > 0 { return fmt.Sprintf("%x", sha1.Sum(bytes)) } return "" } /** * @brief: 默认 */ type defaultAttachUpDownloader struct{ } /** * @brief: 附件上传接口 * @param1 file: post 多媒体file * @param1 header: 文件相头信息 * @return1: 附件信息,主要包括id,url, hash和大小。其他字段会自动设置 * @return2: 错误信息 */ func(d *defaultAttachUpDownloader)Upload(file multipart.File, header *multipart.FileHeader)(*sysmodel.SysAttachment, error){ fileDir := fmt.Sprintf("files/") if err := mkdir(fileDir); err != nil { syslogs.Info("文件夹创建失败") return nil, err } attachId := sysutils.NewUUID() filePath := fileDir + attachId fW, err := os.Create(filePath) if err != nil { syslogs.Info("文件创建失败") return nil, err } defer fW.Close() length, err := io.Copy(fW, file) if err != nil { syslogs.Info("文件保存失败") return nil, err } attach := &sysmodel.SysAttachment{} attach.Id = attachId attach.Url = "/api/v1/sys_attachment/download?id=" + attach.Id attach.Hash = "" attach.Size = int32(length) return attach, nil } /** * @brief: 附件下载 * @param1 ctx: 上下文 * @param2 id: 附件记录的id */ func(d *defaultAttachUpDownloader)Download(c *entitys.CtrlContext, attach *sysmodel.SysAttachment){ filePath := "files/" + attach.Id c.Ctx.Writer.Header().Add("Content-Disposition", "attachment;filename=\""+sysutils.FormatForBrowse(c.Ctx.Request.UserAgent(), attach.Name)+"\"") c.Ctx.Writer.Header().Add("Content-Type", mime.TypeByExtension(attach.Ext)) c.Ctx.Writer.Header().Add("Content-Length", strconv.FormatInt(int64(attach.Size), 10)) c.Ctx.Writer.Header().Add("Accept-Ranges", "bytes") if !sysutils.Exists(filePath) { c.Ctx.Writer.WriteHeader(400) return } fmt.Println("---->", c.Ctx.Writer.Header().Get("Content-Disposition")) fmt.Println("---->", c.Ctx.Writer.Header().Get("Content-Type")) fmt.Println("---->", c.Ctx.Writer.Header().Get("Content-Length")) fmt.Println("---->", c.Ctx.Writer.Header().Get("Accept-Ranges")) c.Ctx.File(filePath) } func __none_func_sys_attachment__(params ...interface{}) bool { return true }