83 lines
1.8 KiB
Go
83 lines
1.8 KiB
Go
|
|
package handlers
|
||
|
|
|
||
|
|
import (
|
||
|
|
"crypto/rand"
|
||
|
|
"encoding/hex"
|
||
|
|
"net/http"
|
||
|
|
"os"
|
||
|
|
"path/filepath"
|
||
|
|
"strconv"
|
||
|
|
"strings"
|
||
|
|
"time"
|
||
|
|
|
||
|
|
"0451meishiditu/backend/internal/resp"
|
||
|
|
|
||
|
|
"github.com/gin-gonic/gin"
|
||
|
|
)
|
||
|
|
|
||
|
|
func (h *Handlers) Upload(c *gin.Context) {
|
||
|
|
url, ok := h.handleUpload(c)
|
||
|
|
if !ok {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
resp.OK(c, gin.H{"url": url})
|
||
|
|
}
|
||
|
|
|
||
|
|
// UserUpload allows logged-in users to upload images for reviews.
|
||
|
|
func (h *Handlers) UserUpload(c *gin.Context) {
|
||
|
|
url, ok := h.handleUpload(c)
|
||
|
|
if !ok {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
resp.OK(c, gin.H{"url": url})
|
||
|
|
}
|
||
|
|
|
||
|
|
func (h *Handlers) handleUpload(c *gin.Context) (string, bool) {
|
||
|
|
maxMB := h.cfg.MaxUploadMB
|
||
|
|
if maxMB <= 0 {
|
||
|
|
maxMB = 10
|
||
|
|
}
|
||
|
|
c.Request.Body = http.MaxBytesReader(c.Writer, c.Request.Body, maxMB*1024*1024)
|
||
|
|
|
||
|
|
file, err := c.FormFile("file")
|
||
|
|
if err != nil {
|
||
|
|
resp.Fail(c, http.StatusBadRequest, "missing file")
|
||
|
|
return "", false
|
||
|
|
}
|
||
|
|
|
||
|
|
ext := strings.ToLower(filepath.Ext(file.Filename))
|
||
|
|
switch ext {
|
||
|
|
case ".jpg", ".jpeg", ".png", ".webp", ".gif":
|
||
|
|
default:
|
||
|
|
resp.Fail(c, http.StatusBadRequest, "unsupported file type")
|
||
|
|
return "", false
|
||
|
|
}
|
||
|
|
|
||
|
|
now := time.Now()
|
||
|
|
dir := filepath.Join(h.cfg.UploadDir, strconv.Itoa(now.Year()), now.Format("01"))
|
||
|
|
if err := os.MkdirAll(dir, 0o755); err != nil {
|
||
|
|
resp.Fail(c, http.StatusInternalServerError, "mkdir failed")
|
||
|
|
return "", false
|
||
|
|
}
|
||
|
|
|
||
|
|
name := randomHex(16) + ext
|
||
|
|
dst := filepath.Join(dir, name)
|
||
|
|
if err := c.SaveUploadedFile(file, dst); err != nil {
|
||
|
|
resp.Fail(c, http.StatusInternalServerError, "save failed")
|
||
|
|
return "", false
|
||
|
|
}
|
||
|
|
|
||
|
|
rel := strings.TrimPrefix(filepath.ToSlash(dst), ".")
|
||
|
|
if !strings.HasPrefix(rel, "/") {
|
||
|
|
rel = "/" + rel
|
||
|
|
}
|
||
|
|
url := strings.TrimRight(h.cfg.PublicBaseURL, "/") + rel
|
||
|
|
return url, true
|
||
|
|
}
|
||
|
|
|
||
|
|
func randomHex(n int) string {
|
||
|
|
b := make([]byte, n)
|
||
|
|
_, _ = rand.Read(b)
|
||
|
|
return hex.EncodeToString(b)
|
||
|
|
}
|