|
|
package filestore
|
|
|
|
|
|
import (
|
|
|
"errors"
|
|
|
"fmt"
|
|
|
"io"
|
|
|
"mime/multipart"
|
|
|
"os"
|
|
|
"path"
|
|
|
|
|
|
"github.com/sony/sonyflake"
|
|
|
)
|
|
|
|
|
|
var (
|
|
|
ImageFilePath string
|
|
|
VoiceFilePath string
|
|
|
VideoFilePath string
|
|
|
)
|
|
|
|
|
|
func init() {
|
|
|
//TODO 初始化文件存储路径,建议手动创建
|
|
|
ImageFilePath = ""
|
|
|
VoiceFilePath = ""
|
|
|
VideoFilePath = ""
|
|
|
// ValidatePath(ImageFilePath)
|
|
|
// ValidatePath(VoiceFilePath)
|
|
|
// ValidatePath(VideoFilePath)
|
|
|
}
|
|
|
|
|
|
//IFileStore 文件存储相关
|
|
|
type IFileStore interface {
|
|
|
StoreFile() (string, error) //实际存储文件操作
|
|
|
}
|
|
|
|
|
|
type IFileReader interface {
|
|
|
ReadFileSrc(id int64) (string, error) //实际获取文件链接
|
|
|
}
|
|
|
|
|
|
func ValidateFileExt(fileExt string) bool {
|
|
|
allowExt := map[string]bool{
|
|
|
"jpg": true,
|
|
|
"png": true,
|
|
|
"mp3": true,
|
|
|
}
|
|
|
if _, ok := allowExt[fileExt]; ok {
|
|
|
return true
|
|
|
}
|
|
|
return false
|
|
|
}
|
|
|
|
|
|
func NewFileStore(fHeader *multipart.FileHeader) (IFileStore, error) {
|
|
|
filename := fHeader.Filename
|
|
|
fileExt := path.Ext(filename)
|
|
|
if ok := ValidateFileExt(fileExt); !ok {
|
|
|
return nil, errors.New("ValidateFileExt fail")
|
|
|
}
|
|
|
var filestore IFileStore
|
|
|
switch fileExt {
|
|
|
case "jpg", "png":
|
|
|
filestore = NewImageFileStore(fHeader, fileExt)
|
|
|
case "mp3":
|
|
|
filestore = NewVideoFileStore(fHeader, fileExt)
|
|
|
}
|
|
|
return filestore, nil
|
|
|
}
|
|
|
|
|
|
func NewReader(filetype string) (IFileReader, error) {
|
|
|
var filestore IFileReader
|
|
|
switch filetype {
|
|
|
case "imgage":
|
|
|
filestore = &ImageFileStore{}
|
|
|
case "mp3":
|
|
|
filestore = &VideoFileStore{}
|
|
|
default:
|
|
|
return nil, fmt.Errorf("err:filetype is %s", filetype)
|
|
|
}
|
|
|
return filestore, nil
|
|
|
}
|
|
|
|
|
|
//ImageFileStore 图片文件
|
|
|
type ImageFileStore struct {
|
|
|
fHeader *multipart.FileHeader
|
|
|
fileType string
|
|
|
size int
|
|
|
}
|
|
|
|
|
|
var (
|
|
|
_ IFileStore = &ImageFileStore{}
|
|
|
)
|
|
|
|
|
|
func NewImageFileStore(fHeader *multipart.FileHeader, filetype string) *ImageFileStore {
|
|
|
return &ImageFileStore{
|
|
|
fHeader: fHeader,
|
|
|
fileType: filetype,
|
|
|
}
|
|
|
}
|
|
|
func (f ImageFileStore) StoreFile() (string, error) {
|
|
|
storePath := fmt.Sprintf("%s%s.%s", ImageFilePath, randomName(), f.fileType)
|
|
|
tempFile, err := f.fHeader.Open()
|
|
|
if err != nil {
|
|
|
return "", err
|
|
|
}
|
|
|
defer tempFile.Close()
|
|
|
if err = SaveToFile(storePath, tempFile); err != nil {
|
|
|
return "", err
|
|
|
}
|
|
|
//数据库操作
|
|
|
return storePath, nil
|
|
|
}
|
|
|
|
|
|
func (f ImageFileStore) ReadFileSrc(id int64) (string, error) {
|
|
|
//数据库操作
|
|
|
return "", nil
|
|
|
}
|
|
|
|
|
|
//VoiceFileStore 音频文件
|
|
|
type VideoFileStore struct {
|
|
|
fHeader *multipart.FileHeader
|
|
|
size int
|
|
|
fileType string
|
|
|
}
|
|
|
|
|
|
var (
|
|
|
_ IFileStore = &VideoFileStore{}
|
|
|
)
|
|
|
|
|
|
func NewVideoFileStore(fHeader *multipart.FileHeader, filetype string) *VideoFileStore {
|
|
|
return &VideoFileStore{
|
|
|
fHeader: fHeader,
|
|
|
fileType: filetype,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
func (f VideoFileStore) StoreFile() (string, error) {
|
|
|
storePath := fmt.Sprintf("%s%s.%s", ImageFilePath, randomName(), f.fileType)
|
|
|
tempFile, err := f.fHeader.Open()
|
|
|
if err != nil {
|
|
|
return "", err
|
|
|
}
|
|
|
defer tempFile.Close()
|
|
|
if err = SaveToFile(storePath, tempFile); err != nil {
|
|
|
return "", err
|
|
|
}
|
|
|
//数据库操作
|
|
|
return storePath, nil
|
|
|
}
|
|
|
|
|
|
func (f VideoFileStore) ReadFileSrc(id int64) (string, error) {
|
|
|
//数据库操作
|
|
|
return "", nil
|
|
|
}
|
|
|
|
|
|
var sf = sonyflake.NewSonyflake(sonyflake.Settings{})
|
|
|
|
|
|
func randomName() string {
|
|
|
num, _ := sf.NextID()
|
|
|
return fmt.Sprintf("%d", num)
|
|
|
}
|
|
|
|
|
|
func ValidatePath(s string) error {
|
|
|
info, err := os.Stat(s)
|
|
|
if err != nil {
|
|
|
return err
|
|
|
}
|
|
|
if ok := info.IsDir(); ok {
|
|
|
return nil
|
|
|
}
|
|
|
return errors.New("path must be directory")
|
|
|
}
|
|
|
|
|
|
func SaveToFile(storePath string, rd io.Reader) error {
|
|
|
openf, err := os.OpenFile(storePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
|
|
|
if err != nil {
|
|
|
return err
|
|
|
}
|
|
|
defer openf.Close()
|
|
|
io.Copy(openf, rd)
|
|
|
return nil
|
|
|
} |