package httpapi import ( "io" "net/http" "strings" "github.com/easyai/easyai-ai-gateway/apps/api/internal/clients" "github.com/easyai/easyai-ai-gateway/apps/api/internal/runner" ) const maxGatewayUploadBytes = 256 << 20 func (s *Server) uploadFile(w http.ResponseWriter, r *http.Request) { r.Body = http.MaxBytesReader(w, r.Body, maxGatewayUploadBytes) if err := r.ParseMultipartForm(32 << 20); err != nil { writeError(w, http.StatusBadRequest, "invalid multipart upload") return } file, header, err := r.FormFile("file") if err != nil { writeError(w, http.StatusBadRequest, "file is required") return } defer file.Close() payload, err := io.ReadAll(file) if err != nil { writeError(w, http.StatusBadRequest, "read upload file failed") return } contentType := strings.TrimSpace(header.Header.Get("Content-Type")) if contentType == "" && len(payload) > 0 { contentType = http.DetectContentType(payload) } upload, err := s.runner.UploadFile(r.Context(), runner.FileUploadPayload{ Bytes: payload, ContentType: contentType, FileName: header.Filename, Source: firstNonEmptyFormValue(r, "source", "ai-gateway-openapi"), }) if err != nil { s.logger.Error("upload file failed", "error", err) status := http.StatusBadGateway if clients.ErrorCode(err) == "upload_no_channel" { status = http.StatusServiceUnavailable } writeError(w, status, err.Error()) return } writeJSON(w, http.StatusOK, upload) } func firstNonEmptyFormValue(r *http.Request, key string, fallback string) string { if value := strings.TrimSpace(r.FormValue(key)); value != "" { return value } return fallback }