package request import ( "bytes" "encoding/base64" "encoding/json" "io" "lone-services/bff/internal/response" "lone-services/pkg/oss" "net/http" "path/filepath" "strings" ) const ( ossUploadAPIPath = "/api/v3/chore/oss/upload" formFileField = "file" maxUploadMemory = oss.MaxUploadBytes ) func FormUploadMiddleware(next http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost || r.URL.Path != ossUploadAPIPath { next(w, r) return } ct := r.Header.Get("Content-Type") ctrl := &response.BaseController{} if !strings.HasPrefix(strings.ToLower(ct), "multipart/form-data") { ctrl.Error(w, response.Define(response.ErrorMissingParams, "请使用 multipart/form-data 上传,字段名为 file")) return } if err := r.ParseMultipartForm(int64(maxUploadMemory)); err != nil { ctrl.Error(w, response.Define(response.ErrorMissingParams, "解析上传文件失败")) return } file, header, err := r.FormFile(formFileField) if err != nil { ctrl.Error(w, response.Define(response.ErrorMissingParams, "请上传文件,字段名为 file")) return } defer file.Close() content, err := io.ReadAll(io.LimitReader(file, int64(maxUploadMemory)+1)) if err != nil || len(content) == 0 { ctrl.Error(w, response.Define(response.ErrorMissingParams, "文件内容不能为空")) return } if len(content) > maxUploadMemory { ctrl.Error(w, response.Define(response.ErrorMissingParams, "文件过大,最大 128MB")) return } filename := filepath.Base(header.Filename) if filename == "." || filename == "" { filename = "file" } payload, err := json.Marshal(map[string]string{ "filename": filename, "content": base64.StdEncoding.EncodeToString(content), }) if err != nil { ctrl.Fail(w) return } r.Body = io.NopCloser(bytes.NewReader(payload)) r.ContentLength = int64(len(payload)) r.Header.Set("Content-Type", "application/json") next(w, r) } }