package admin import ( "context" "log/slog" "net/http" "path/filepath" "server/internal/config" "server/internal/model/common" "server/internal/model/request" "server/internal/pkg/errs" "server/internal/pkg/httputil" "server/internal/pkg/safego" "server/internal/pkg/validator" "server/internal/router" "server/internal/service/admin" "strings" "github.com/go-chi/chi/v5" ) type FileHandler struct { service *admin.FileService logger *slog.Logger cfg *config.Config } var _ router.Registrar = (*FileHandler)(nil) func NewFileHandler(service *admin.FileService, logger *slog.Logger, cfg *config.Config) *FileHandler { return &FileHandler{ service: service, logger: logger, cfg: cfg, } } func (h *FileHandler) Register(r chi.Router) { r.Route("/files", func(r chi.Router) { r.Get("/", h.List) r.Post("/", h.Upload) r.Post("/sync-metadata", h.SyncMetadata) }) } func (h *FileHandler) List(w http.ResponseWriter, r *http.Request) { pagination := httputil.Pagination(r) result, err := h.service.List(r.Context(), pagination) if err != nil { httputil.Fail(w, err) return } resp := common.PageResponse{ Page: pagination.Page, PageSize: pagination.PageSize, List: result.List, Total: result.Total, } httputil.OkWithPage(w, &resp) } func (h *FileHandler) Upload(w http.ResponseWriter, r *http.Request) { // 限制上传大小(默认 10MB) maxSize := h.cfg.File.MaxUploadSize if maxSize <= 0 { maxSize = 10 << 20 // 10MB } r.Body = http.MaxBytesReader(w, r.Body, maxSize) folder := r.FormValue("folder") req := request.UploadFileRequest{Folder: folder} if err := validator.Struct(&req); err != nil { httputil.Fail(w, err) return } _, header, err := r.FormFile("file") if err != nil { httputil.Fail(w, err) return } // 扩展名白名单 ext := strings.ToLower(filepath.Ext(header.Filename)) if !request.IsAllowedUploadExt(ext) { httputil.Fail(w, errs.ErrFileTypeNotAllowed) return } file, err := h.service.Upload(r.Context(), folder, header) if err != nil { httputil.Fail(w, err) return } httputil.Ok(w, file) } func (h *FileHandler) SyncMetadata(w http.ResponseWriter, r *http.Request) { safego.Go(func() { if err := h.service.SyncMetadata(context.Background()); err != nil { h.logger.Error("sync metadata failed", "error", err) } }) httputil.Ok(w) }