package file import ( "errors" "fmt" "io" "mime/multipart" "os" "path" "time" "github.com/h2non/filetype" gonanoid "github.com/matoous/go-nanoid/v2" ) const ( MaxImageSize = 10 << 20 // 10 MB MaxFileSize = 50 << 20 // 50 MB ) var ErrUnsupported = errors.New("文件格式不支持") type FileType int const ( ALL FileType = 0 IMG FileType = 1 ) func UploadFilename(filepath string, t FileType) (string, error) { fileOpen, err := os.Open(filepath) if err != nil { return "", err } defer fileOpen.Close() fileBytes, err := io.ReadAll(fileOpen) if err != nil { return "", errors.New("failed to read file") } if t == IMG { // 判断是不是图片 if !filetype.IsImage(fileBytes) { return "", ErrUnsupported } } kind, err := filetype.Match(fileBytes) if err != nil { return "", err } if kind == filetype.Unknown { return "", ErrUnsupported } // 使用 filetype 判断类型后已经去读了一些bytes了 // 要恢复文件读取位置 _, err = fileOpen.Seek(0, io.SeekStart) if err != nil { return "", err } dir := GetPath() exist, _ := Exists(dir) if !exist { if err := Mkdir(dir); err != nil { return "", err } } filename := GenFilename(kind.Extension) path := path.Join(dir, filename) f, err := os.Create(path) if err != nil { return "", err } defer f.Close() _, err = io.Copy(f, fileOpen) if err != nil { return "", err } return "/" + path, nil } func UploadFile(file *multipart.FileHeader, t FileType) (string, error) { if file.Size > MaxFileSize { return "", errors.New("failed to receive file too large") } fileOpen, err := file.Open() if err != nil { return "", errors.New("fialed to open file") } defer fileOpen.Close() fileBytes, err := io.ReadAll(fileOpen) if err != nil { return "", errors.New("failed to read file") } if t == IMG { // 判断是不是图片 if !filetype.IsImage(fileBytes) { return "", ErrUnsupported } } kind, err := filetype.Match(fileBytes) if err != nil { return "", err } if kind == filetype.Unknown { return "", ErrUnsupported } // 使用 filetype 判断类型后已经去读了一些bytes了 // 要恢复文件读取位置 _, err = fileOpen.Seek(0, io.SeekStart) if err != nil { return "", err } dir := GetPath() exist, _ := Exists(dir) if !exist { if err := Mkdir(dir); err != nil { return "", err } } filename := GenFilename(kind.Extension) path := path.Join(dir, filename) f, err := os.Create(path) if err != nil { return "", err } defer f.Close() _, err = io.Copy(f, fileOpen) if err != nil { return "", err } return "/" + path, nil } func GetPath() string { return fmt.Sprintf("public/%s/%s/%s/", time.Now().Format("2006"), time.Now().Format("01"), time.Now().Format("02")) } func GenFilename(ext string) string { id, _ := gonanoid.New() return fmt.Sprintf("%s.%s", id, ext) }