package file import ( "crypto/md5" "encoding/hex" "icloudapp.cn/tools/util" "io" "mime/multipart" "os" "path" "strconv" "strings" "time" ) type Upload struct { Path string Allowed map[string]bool HasHash bool } // FileWithErr 用于返回一组上传的文件信息 type FileWithErr struct { Err error FileInfo *File } type File struct { //上传文件名 Name string `json:"name"` //上传后文件路径 File string `json:"file"` Basename string `json:"basename"` //文件大小 Size int64 `json:"size"` //文件Hash Hash string `json:"hash"` //文件类型 Mine string `json:"mine"` } func NewUpload(dir string) *Upload { return &Upload{ Path: dir, } } // 是否返回文件的hash func (u *Upload) SetHasHash(hashash bool) { u.HasHash = hashash } // 设置上传目录 func (u *Upload) SetUploadPath(dir string) { u.Path = dir } // 设置允许的文件类型 func (u *Upload) SetAllowed(allowed map[string]bool) { u.Allowed = allowed } // 追加允许的文件类型 func (u *Upload) AppendAllow(ext string) { u.Allowed[ext] = true } // 上传单个文件 func (u *Upload) Single(file multipart.FileHeader) (*File, error) { res := &File{} extName := strings.ToLower(path.Ext(file.Filename)) if _, ok := u.Allowed[extName]; !ok { return res, util.NewError("不允许的上传类型") } res.Name = file.Filename res.Size = file.Size res.Mine = file.Header.Get("Content-Type") if !IsDir(u.Path) { if err := os.MkdirAll(u.Path, 0750); err != nil { return nil, util.NewError("目录创建失败", u.Path) } } fileUnixName := strconv.FormatInt(time.Now().UnixNano(), 10) res.Basename = fileUnixName + extName savePath := path.Join(u.Path, res.Basename) res.File = savePath src, err := file.Open() if err != nil { return nil, util.NewError("文件打开失败:", err.Error()) } defer src.Close() out, err := os.Create(savePath) if err != nil { return nil, util.NewError("文件创建失败:", err.Error()) } defer out.Close() if u.HasHash { res.Hash = u.FileHash(savePath) } _, err = io.Copy(out, src) return res, nil } // Multiple 上传多个文件 func (u *Upload) Multiple(files []multipart.FileHeader) ([]*FileWithErr, error) { var res []*FileWithErr for key, file := range files { uploaded, err := u.Single(file) res[key] = &FileWithErr{Err: err, FileInfo: uploaded} } return res, nil } // FileHash 获取文件的hash值 func (u *Upload) FileHash(path string) string { file, _ := os.Open(path) m := md5.New() _, err := io.Copy(m, file) if err == nil { hash := m.Sum(nil) return hex.EncodeToString(hash) } return "" }