package common import ( "errors" "fmt" "os" "path/filepath" "strings" "time" "github.com/gogf/gf/v2/net/ghttp" ) var allowedImageExt = map[string]bool{".jpg": true, ".jpeg": true, ".png": true, ".webp": true} // SaveUploadedFile 保存上传文件到 workspace/{subDir},返回访问路径 /workspace/{subDir}/{filename} func SaveUploadedFile(file *ghttp.UploadFile, subDir string) (string, error) { if file == nil { return "", errors.New("未收到文件") } ext := strings.ToLower(filepath.Ext(file.Filename)) if !allowedImageExt[ext] { return "", errors.New("仅支持 jpg/jpeg/png/webp 格式") } if file.Size > 10*1024*1024 { return "", errors.New("单张图片不能超过 10MB") } dir := filepath.Join("workspace", subDir) if err := os.MkdirAll(dir, 0o755); err != nil { return "", err } filename := fmt.Sprintf("%d%s", time.Now().UnixNano(), ext) path := filepath.Join(dir, filename) if _, err := file.Save(path); err != nil { return "", err } return "/" + filepath.ToSlash(filepath.Join("workspace", subDir, filename)), nil } // RemoveWorkspaceFile 删除 workspace 下文件(路径穿越防护) func RemoveWorkspaceFile(url string) error { rel := strings.TrimPrefix(url, "/workspace/") if rel == "" || strings.Contains(rel, "..") { return errors.New("非法文件路径") } abs := filepath.Join("workspace", rel) if _, err := os.Stat(abs); os.IsNotExist(err) { return nil } return os.Remove(abs) }