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("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)
 | |
| }
 |