160 lines
2.8 KiB
Go
160 lines
2.8 KiB
Go
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("upload/%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)
|
|
}
|