101 lines
2.2 KiB
Go
101 lines
2.2 KiB
Go
package upload
|
|
|
|
import (
|
|
"errors"
|
|
"io"
|
|
"mime/multipart"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"sync"
|
|
"time"
|
|
|
|
"kra/pkg/utils"
|
|
)
|
|
|
|
var mu sync.Mutex
|
|
|
|
// Local 本地存储
|
|
type Local struct {
|
|
StorePath string
|
|
BasePath string
|
|
}
|
|
|
|
// NewLocal 创建本地存储
|
|
func NewLocal(storePath, basePath string) *Local {
|
|
return &Local{
|
|
StorePath: storePath,
|
|
BasePath: basePath,
|
|
}
|
|
}
|
|
|
|
// UploadFile 上传文件
|
|
func (l *Local) UploadFile(file *multipart.FileHeader) (string, string, error) {
|
|
// 读取文件后缀
|
|
ext := filepath.Ext(file.Filename)
|
|
// 读取文件名并加密
|
|
name := strings.TrimSuffix(file.Filename, ext)
|
|
name = utils.MD5V([]byte(name))
|
|
// 拼接新文件名
|
|
filename := name + "_" + time.Now().Format("20060102150405") + ext
|
|
|
|
// 尝试创建此路径
|
|
mkdirErr := os.MkdirAll(l.StorePath, os.ModePerm)
|
|
if mkdirErr != nil {
|
|
return "", "", errors.New("function os.MkdirAll() failed, err:" + mkdirErr.Error())
|
|
}
|
|
|
|
// 拼接路径和文件名
|
|
p := l.StorePath + "/" + filename
|
|
filePath := l.BasePath + "/" + filename
|
|
|
|
f, openError := file.Open() // 读取文件
|
|
if openError != nil {
|
|
return "", "", errors.New("function file.Open() failed, err:" + openError.Error())
|
|
}
|
|
defer f.Close()
|
|
|
|
out, createErr := os.Create(p)
|
|
if createErr != nil {
|
|
return "", "", errors.New("function os.Create() failed, err:" + createErr.Error())
|
|
}
|
|
defer out.Close()
|
|
|
|
_, copyErr := io.Copy(out, f) // 传输(拷贝)文件
|
|
if copyErr != nil {
|
|
return "", "", errors.New("function io.Copy() failed, err:" + copyErr.Error())
|
|
}
|
|
return filePath, filename, nil
|
|
}
|
|
|
|
// DeleteFile 删除文件
|
|
func (l *Local) DeleteFile(key string) error {
|
|
// 检查 key 是否为空
|
|
if key == "" {
|
|
return errors.New("key不能为空")
|
|
}
|
|
|
|
// 验证 key 是否包含非法字符或尝试访问存储路径之外的文件
|
|
if strings.Contains(key, "..") || strings.ContainsAny(key, `\/:*?"<>|`) {
|
|
return errors.New("非法的key")
|
|
}
|
|
|
|
p := filepath.Join(l.StorePath, key)
|
|
|
|
// 检查文件是否存在
|
|
if _, err := os.Stat(p); os.IsNotExist(err) {
|
|
return errors.New("文件不存在")
|
|
}
|
|
|
|
// 使用文件锁防止并发删除
|
|
mu.Lock()
|
|
defer mu.Unlock()
|
|
|
|
err := os.Remove(p)
|
|
if err != nil {
|
|
return errors.New("文件删除失败: " + err.Error())
|
|
}
|
|
|
|
return nil
|
|
}
|