package handlers import ( "log" "fmt" "mime" "net/http" "path/filepath" "strings" "time" "github.com/gin-gonic/gin" "go-dy/internal/config" osspkg "go-dy/internal/oss" "go-dy/internal/resp" ) func UploadHandler(cfg config.Config) gin.HandlerFunc { return func(c *gin.Context) { fileHeader, err := c.FormFile("file") if err != nil { resp.Error(c, http.StatusBadRequest, "missing file") return } f, err := fileHeader.Open() if err != nil { log.Printf("file open failed: filename=%s, err=%v", fileHeader.Filename, err) resp.Error(c, http.StatusInternalServerError, "file open failed") return } defer f.Close() prefix := c.PostForm("prefix") prefix = strings.Trim(prefix, "/ ") if prefix == "" { prefix = time.Now().Format("uploads/2006/01/02") } base := filepath.Base(fileHeader.Filename) ts := time.Now().UnixNano() objectKey := fmt.Sprintf("%s/%d_%s", prefix, ts, base) ct := fileHeader.Header.Get("Content-Type") if ct == "" { ct = mime.TypeByExtension(filepath.Ext(base)) } // Lazy init OSS client to avoid startup dependency on OSS params oss, err := osspkg.New(cfg) if err != nil { log.Printf("oss init failed: endpoint=%s bucket=%s err=%v", cfg.OSSEndpoint, cfg.OSSBucket, err) resp.Error(c, http.StatusInternalServerError, "upload failed") return } if err := oss.Upload(objectKey, f, ct); err != nil { log.Printf("oss upload failed: key=%s contentType=%s err=%v", objectKey, ct, err) resp.Error(c, http.StatusInternalServerError, "upload failed") return } url := oss.PublicURL(objectKey) log.Printf("oss upload success: key=%s url=%s", objectKey, url) resp.OK(c, gin.H{ "key": objectKey, "url": url, }) } }