diff --git a/backend/internal/modules/file/handler.go b/backend/internal/modules/file/handler.go index f82586c..d59a136 100644 --- a/backend/internal/modules/file/handler.go +++ b/backend/internal/modules/file/handler.go @@ -94,15 +94,7 @@ func (h *Handler) writeObject(c *gin.Context, publicOnly bool) { response.BadRequest(c, "文件 key 不正确") return } - if publicOnly && - !strings.HasPrefix(key, "home-banner/") && - !strings.HasPrefix(key, "avatar/") && - !strings.HasPrefix(key, "announcement/") && - !strings.HasPrefix(key, "mohong/") && - !strings.HasPrefix(key, "crash/") && - !strings.HasPrefix(key, "aw-recycle/") && - !strings.HasPrefix(key, "cooperation-feedback/") && - !strings.HasPrefix(key, "support-qrcode/") { + if publicOnly && !isPublicObjectKey(key) { response.Error(c, http.StatusNotFound, "not_found", "文件不存在或暂不可访问") return } @@ -142,10 +134,33 @@ func (h *Handler) writeObject(c *gin.Context, publicOnly bool) { contentType = "application/octet-stream" } c.Header("Content-Type", contentType) - c.Header("Cache-Control", "private, max-age=300") + if publicOnly { + c.Header("Cache-Control", "public, max-age=86400") + } else { + c.Header("Cache-Control", "private, max-age=300") + } c.DataFromReader(http.StatusOK, object.Size, contentType, object.Reader, nil) } +func isPublicObjectKey(key string) bool { + for _, prefix := range []string{ + "home-banner/", + "avatar/", + "announcement/", + "mohong/", + "crash/", + "aw-recycle/", + "cooperation-feedback/", + "support-qrcode/", + "points-mall/", + } { + if strings.HasPrefix(key, prefix) { + return true + } + } + return false +} + func writeFileError(c *gin.Context, err error) { response.RecordError(c, err) switch { diff --git a/backend/internal/modules/file/storage_test.go b/backend/internal/modules/file/storage_test.go index e59fda2..1500344 100644 --- a/backend/internal/modules/file/storage_test.go +++ b/backend/internal/modules/file/storage_test.go @@ -95,6 +95,9 @@ func TestPointsMallSceneUsesPublicFileURL(t *testing.T) { if !strings.HasPrefix(got, "/api/public/files/object?") { t.Fatalf("points-mall file url = %q, want public file endpoint", got) } + if !isPublicObjectKey("points-mall/2026/11/04/example.webp") { + t.Fatal("points-mall object should be publicly readable") + } } func TestNormalizeSceneListingScreenshotAndOperatingExpense(t *testing.T) {