Files
assetx/webapp-back/admin/upload.go

100 lines
2.4 KiB
Go
Raw Normal View History

package admin
import (
"fmt"
"net/http"
"os"
"path/filepath"
"strings"
"time"
"github.com/gin-gonic/gin"
)
var allowedCategories = map[string]bool{
"reports": true,
"custody": true,
"links": true,
}
var allowedExts = map[string]bool{
".pdf": true,
".png": true,
".jpg": true,
".jpeg": true,
".doc": true,
".docx": true,
".txt": true,
".xls": true,
".xlsx": true,
}
// UploadFile handles multipart file uploads, saves to ./uploads/{category}/, returns accessible URL.
// Query param: category (reports|custody), defaults to "reports".
func UploadFile(c *gin.Context) {
file, err := c.FormFile("file")
if err != nil {
Fail(c, http.StatusBadRequest, "No file provided")
return
}
ext := strings.ToLower(filepath.Ext(file.Filename))
if !allowedExts[ext] {
Fail(c, http.StatusBadRequest, "File type not allowed")
return
}
category := c.DefaultQuery("category", "reports")
if !allowedCategories[category] {
Fail(c, http.StatusBadRequest, "Invalid category")
return
}
dir := "uploads/" + category
if err := os.MkdirAll(dir, 0755); err != nil {
Fail(c, http.StatusInternalServerError, "Failed to create upload directory")
return
}
filename := fmt.Sprintf("%d_%s", time.Now().UnixNano(), filepath.Base(file.Filename))
dst := filepath.Join(dir, filename)
if err := c.SaveUploadedFile(file, dst); err != nil {
Fail(c, http.StatusInternalServerError, "Failed to save file")
return
}
url := "/uploads/" + category + "/" + filename
OK(c, gin.H{"url": url})
}
// DeleteUploadedFile deletes a previously uploaded file by its URL path.
func DeleteUploadedFile(c *gin.Context) {
urlPath := c.Query("path") // e.g. /uploads/reports/xxx.pdf or /uploads/custody/xxx.pdf
if !strings.HasPrefix(urlPath, "/uploads/") {
Fail(c, http.StatusBadRequest, "Invalid file path")
return
}
if strings.Contains(urlPath, "..") {
Fail(c, http.StatusBadRequest, "Invalid file path")
return
}
// Verify the second segment is a known category
parts := strings.SplitN(strings.TrimPrefix(urlPath, "/uploads/"), "/", 2)
if len(parts) != 2 || !allowedCategories[parts[0]] {
Fail(c, http.StatusBadRequest, "Invalid file path")
return
}
localPath := strings.TrimPrefix(urlPath, "/")
if err := os.Remove(localPath); err != nil {
if os.IsNotExist(err) {
OK(c, gin.H{"message": "file not found, skipped"})
return
}
Fail(c, http.StatusInternalServerError, "Failed to delete file")
return
}
OK(c, gin.H{"message": "deleted"})
}