From 2b9fd4e7e06c53d6b388ccc36622f27967d1da81 Mon Sep 17 00:00:00 2001 From: Bryan1029384756 <23323626+Bryan1029384756@users.noreply.github.com> Date: Mon, 16 Feb 2026 19:15:11 -0600 Subject: [PATCH] Max file upload 500MB --- convex/files.ts | 19 +++++++++++++++++++ packages/shared/src/components/ChatArea.jsx | 5 +++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/convex/files.ts b/convex/files.ts index e1e031c..7bf67c7 100644 --- a/convex/files.ts +++ b/convex/files.ts @@ -12,6 +12,25 @@ export const generateUploadUrl = mutation({ }, }); +const MAX_ATTACHMENT_SIZE = 500 * 1024 * 1024; // 500MB + +// Validate uploaded file size and return its URL. Deletes file if too large. +export const validateUpload = mutation({ + args: { storageId: v.id("_storage") }, + returns: v.string(), + handler: async (ctx, args) => { + const meta = await ctx.storage.getMetadata(args.storageId); + if (!meta) throw new Error("File not found in storage"); + if (meta.size > MAX_ATTACHMENT_SIZE) { + await ctx.storage.delete(args.storageId); + throw new Error("File must be under 500MB"); + } + const url = await getPublicStorageUrl(ctx, args.storageId); + if (!url) throw new Error("Failed to get file URL"); + return url; + }, +}); + // Get file URL from storage ID export const getFileUrl = query({ args: { storageId: v.id("_storage") }, diff --git a/packages/shared/src/components/ChatArea.jsx b/packages/shared/src/components/ChatArea.jsx index a759bba..b80954f 100644 --- a/packages/shared/src/components/ChatArea.jsx +++ b/packages/shared/src/components/ChatArea.jsx @@ -1072,7 +1072,8 @@ const ChatArea = ({ channelId, channelName, channelType, username, channelKey, u setInput(inputDivRef.current.textContent); }; - const processFile = (file) => { setPendingFiles(prev => [...prev, file]); }; + const MAX_ATTACHMENT_SIZE = 500 * 1024 * 1024; // 500MB + const processFile = (file) => { if (file.size > MAX_ATTACHMENT_SIZE) { alert('File must be under 500MB'); return; } setPendingFiles(prev => [...prev, file]); }; const handleFileSelect = (e) => { if (e.target.files && e.target.files.length > 0) Array.from(e.target.files).forEach(processFile); }; const isExternalFileDrag = (e) => { const types = Array.from(e.dataTransfer.types); @@ -1095,7 +1096,7 @@ const ChatArea = ({ channelId, channelName, channelType, username, channelKey, u const uploadRes = await fetch(uploadUrl, { method: 'POST', headers: { 'Content-Type': blob.type }, body: blob }); const { storageId } = await uploadRes.json(); - const fileUrl = await convex.query(api.files.getFileUrl, { storageId }); + const fileUrl = await convex.mutation(api.files.validateUpload, { storageId }); const metadata = { type: 'attachment',