package file import ( "errors" "fmt" "io" "mime/multipart" "os" "path" "time" "github.com/google/uuid" "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 Type int const ( ALL Type = 0 IMG Type = 1 ) //func UploadFilename(filepath string, t Type) (string, error) { // fileOpen, err := os.Open(filepath) // if err != nil { // return "", err // } // defer func(fileOpen *os.File) { // _ = fileOpen.Close() // }(fileOpen) // // 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) // fullPath := path.Join(dir, filename) // f, err := os.Create(fullPath) // if err != nil { // return "", err // } // defer func(f *os.File) { // _ = f.Close() // }(f) // // _, err = io.Copy(f, fileOpen) // if err != nil { // return "", err // } // // return "/" + fullPath, nil //} func UploadFile(file *multipart.FileHeader, t Type) (string, error) { if t == IMG { if file.Size > MaxImageSize { return "", errors.New("failed to receive images too large") } } else { if file.Size > MaxFileSize { return "", errors.New("failed to receive file too large") } } fileOpen, err := file.Open() if err != nil { return "", errors.New("failed to open file") } defer func(fileOpen multipart.File) { _ = fileOpen.Close() }(fileOpen) 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) fullPath := path.Join(dir, filename) f, err := os.Create(fullPath) if err != nil { return "", err } defer func(f *os.File) { _ = f.Close() }(f) _, err = io.Copy(f, fileOpen) if err != nil { return "", err } return "/" + fullPath, 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, err := gonanoid.New() if err != nil { return uuid.New().String() } return fmt.Sprintf("%s.%s", id, ext) }