From 10a3df3a5aa4f3884b5b58d33fa2e120781c2abb Mon Sep 17 00:00:00 2001 From: zhx Date: Tue, 2 Jun 2026 18:23:45 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=89=B9=E9=87=8F=E4=B8=8A?= =?UTF-8?q?=E4=BC=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/internal/modules/upload/handler.go | 4 +++ .../internal/modules/upload/handler_test.go | 29 +++++++++++++++++++ .../admin/internal/modules/upload/routes.go | 1 + 3 files changed, 34 insertions(+) diff --git a/server/admin/internal/modules/upload/handler.go b/server/admin/internal/modules/upload/handler.go index 14dd4c9d..7df42fc9 100644 --- a/server/admin/internal/modules/upload/handler.go +++ b/server/admin/internal/modules/upload/handler.go @@ -63,6 +63,10 @@ func (h *Handler) UploadImage(c *gin.Context) { h.uploadObject(c, imageUploadPolicy) } +func (h *Handler) UploadFilesBatch(c *gin.Context) { + h.uploadObjects(c, fileUploadPolicy) +} + func (h *Handler) UploadImagesBatch(c *gin.Context) { h.uploadObjects(c, imageUploadPolicy) } diff --git a/server/admin/internal/modules/upload/handler_test.go b/server/admin/internal/modules/upload/handler_test.go index d3c50364..ea6e380f 100644 --- a/server/admin/internal/modules/upload/handler_test.go +++ b/server/admin/internal/modules/upload/handler_test.go @@ -187,6 +187,28 @@ func TestUploadImagesBatchUploadsSeriallyAndLimitsCount(t *testing.T) { } } +func TestUploadFilesBatchAllowsAnyMaterialExtension(t *testing.T) { + uploader := &fakeUploader{} + handler := New(uploader, "admin", fakeAudit{}) + router := ginRouter(handler) + body, contentType := multipartBatchUploadBody(t, []string{"gift.mp4", "gift.json"}) + req := httptest.NewRequest(http.MethodPost, "/upload-files-batch", body) + req.Header.Set("Content-Type", contentType) + rec := httptest.NewRecorder() + + router.ServeHTTP(rec, req) + + if rec.Code != http.StatusOK { + t.Fatalf("status = %d body=%s", rec.Code, rec.Body.String()) + } + if len(uploader.keys) != 2 { + t.Fatalf("expected 2 uploads, got %d", len(uploader.keys)) + } + if !strings.HasPrefix(uploader.keys[0], "admin/files/7/") || !strings.HasSuffix(uploader.keys[0], ".mp4") { + t.Fatalf("unexpected first key: %s", uploader.keys[0]) + } +} + func ginRouter(handler *Handler) http.Handler { router := gin.New() router.Use(func(c *gin.Context) { @@ -195,6 +217,7 @@ func ginRouter(handler *Handler) http.Handler { c.Next() }) router.POST("/upload-image", handler.UploadImage) + router.POST("/upload-files-batch", handler.UploadFilesBatch) router.POST("/upload-images-batch", handler.UploadImagesBatch) return router } @@ -229,6 +252,12 @@ func multipartBatchUploadBody(t *testing.T, filenames []string) (*bytes.Buffer, if strings.HasSuffix(filename, ".pag") { contentType = "application/octet-stream" payload = []byte("PAG animated asset") + } else if strings.HasSuffix(filename, ".mp4") { + contentType = "video/mp4" + payload = []byte("mp4 animated asset") + } else if strings.HasSuffix(filename, ".json") { + contentType = "application/json" + payload = []byte(`{"asset":true}`) } part, err := writer.CreatePart(map[string][]string{ "Content-Disposition": {`form-data; name="files"; filename="` + filename + `"`}, diff --git a/server/admin/internal/modules/upload/routes.go b/server/admin/internal/modules/upload/routes.go index 218aa5ea..3abeb0ca 100644 --- a/server/admin/internal/modules/upload/routes.go +++ b/server/admin/internal/modules/upload/routes.go @@ -13,5 +13,6 @@ func RegisterRoutes(protected *gin.RouterGroup, h *Handler) { protected.POST("/admin/files/upload", middleware.RequirePermission("upload:create"), h.UploadFile) protected.POST("/admin/files/image/upload", middleware.RequirePermission("upload:create"), h.UploadImage) + protected.POST("/admin/files/batch-upload", middleware.RequirePermission("upload:create"), h.UploadFilesBatch) protected.POST("/admin/files/image/batch-upload", middleware.RequirePermission("upload:create"), h.UploadImagesBatch) }