fix(upload): remove file type allowlist to support all file types (#329)

* fix(upload): remove file type allowlist to support all file types

Removes the hardcoded MIME type allowlist from both frontend and backend
that was blocking uploads of file types like Word documents (.docx).
File size limit (10 MB) is still enforced. Content type detection is
preserved for metadata storage.

Closes MUL-123

* feat(upload): increase file size limit from 10 MB to 100 MB

Updates both frontend and backend to allow uploads up to 100 MB.
This commit is contained in:
LinYushen 2026-04-02 13:55:50 +08:00 committed by GitHub
parent f353e8db59
commit ff616de82b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 3 additions and 60 deletions

View file

@ -5,31 +5,7 @@ import { toast } from "sonner";
import { api } from "@/shared/api"; import { api } from "@/shared/api";
import type { Attachment } from "@/shared/types"; import type { Attachment } from "@/shared/types";
const MAX_FILE_SIZE = 10 * 1024 * 1024; // 10 MB const MAX_FILE_SIZE = 100 * 1024 * 1024; // 100 MB
const ALLOWED_TYPES = new Set([
"image/png",
"image/jpeg",
"image/gif",
"image/webp",
"image/svg+xml",
"application/pdf",
"text/plain",
"text/csv",
"application/json",
"video/mp4",
"video/webm",
"audio/mpeg",
"audio/wav",
"application/zip",
]);
function isAllowedType(type: string): boolean {
// Empty MIME type (browser couldn't determine) — let the server sniff and decide.
if (!type) return true;
const mediaType = type.split(";")[0] ?? "";
return ALLOWED_TYPES.has(mediaType.trim().toLowerCase());
}
export interface UploadResult { export interface UploadResult {
id: string; id: string;
@ -48,10 +24,7 @@ export function useFileUpload() {
const upload = useCallback( const upload = useCallback(
async (file: File, ctx?: UploadContext): Promise<UploadResult | null> => { async (file: File, ctx?: UploadContext): Promise<UploadResult | null> => {
if (file.size > MAX_FILE_SIZE) { if (file.size > MAX_FILE_SIZE) {
throw new Error("File exceeds 10 MB limit"); throw new Error("File exceeds 100 MB limit");
}
if (!isAllowedType(file.type)) {
throw new Error(`File type not allowed: ${file.type}`);
} }
setUploading(true); setUploading(true);

View file

@ -9,7 +9,6 @@ import (
"log/slog" "log/slog"
"net/http" "net/http"
"path" "path"
"strings"
"time" "time"
"github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5"
@ -17,32 +16,7 @@ import (
db "github.com/multica-ai/multica/server/pkg/db/generated" db "github.com/multica-ai/multica/server/pkg/db/generated"
) )
const maxUploadSize = 10 << 20 // 10 MB const maxUploadSize = 100 << 20 // 100 MB
// Allowed MIME type prefixes and exact types for uploads.
var allowedContentTypes = map[string]bool{
"image/png": true,
"image/jpeg": true,
"image/gif": true,
"image/webp": true,
"image/svg+xml": true,
"application/pdf": true,
"text/plain": true,
"text/csv": true,
"application/json": true,
"video/mp4": true,
"video/webm": true,
"audio/mpeg": true,
"audio/wav": true,
"application/zip": true,
}
func isContentTypeAllowed(ct string) bool {
// Normalize: take only the media type, strip parameters like charset.
ct = strings.TrimSpace(strings.SplitN(ct, ";", 2)[0])
ct = strings.ToLower(ct)
return allowedContentTypes[ct]
}
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Response types // Response types
@ -148,10 +122,6 @@ func (h *Handler) UploadFile(w http.ResponseWriter, r *http.Request) {
return return
} }
contentType := http.DetectContentType(buf[:n]) contentType := http.DetectContentType(buf[:n])
if !isContentTypeAllowed(contentType) {
writeError(w, http.StatusBadRequest, fmt.Sprintf("file type not allowed: %s", contentType))
return
}
// Seek back so the full file is uploaded. // Seek back so the full file is uploaded.
if _, err := file.Seek(0, io.SeekStart); err != nil { if _, err := file.Seek(0, io.SeekStart); err != nil {
writeError(w, http.StatusInternalServerError, "failed to read file") writeError(w, http.StatusInternalServerError, "failed to read file")