[▲ Vercel Community](/) · [Categories](/categories) · [Latest](/latest) · [Top](/top) · [Live](/live) [Discussions](/c/community/4) # How to upload multiple files to Vercel Blob with progress trackers 171 views · 0 likes · 2 posts Justin Harr (@harrjm) · 2025-06-11  I'm basically trying to replicate what Vercel Blob itself does in the screenshot above, allow multiple file uploads at once and track the progress of each. I handled it like this and it seems to work ok, but it's one of those things that I'd really love to see an official example or at least get more eyes on. ``` async function handleSubmit(e: FormEvent<HTMLFormElement>) { e.preventDefault(); if (files.length) { setIsUploading(true); try { // Upload files concurrently const uploadPromises = files.map(async (fileProgress, index) => { if (fileProgress.status !== "pending") return; try { // Update status to uploading setFiles((prev) => prev.map((f, i) => i === index ? { ...f, status: "uploading" as const } : f ) ); // Upload the fie const blob = await upload( fileProgress.file.name, fileProgress.file, { access: "public", handleUploadUrl: "/api/upload", multipart: true, onUploadProgress: ({ percentage }) => { // Update the progress setFiles((prev) => prev.map((f, i) => i === index ? { ...f, progress: percentage } : f ) ); }, } ); // Update status to completed setFiles((prev) => prev.map((f, i) => i === index ? { ...f, status: "completed" as const, url: blob.url, progress: 100, } : f ) ); } catch (error) { // Update status to error setFiles((prev) => prev.map((f, i) => i === index ? { ...f, status: "error" as const, error: error instanceof Error ? error.message : "Upload failed", } : f ) ); } }); await Promise.allSettled(uploadPromises); setIsUploading(false); notifications.show({ color: "green", title: "File uploaded!", message: `Your files have been uploaded`, }); } catch (error) { notifications.show({ color: "red", title: "Error", message: error.message, }); } } } ``` Pauline P. Narvas (@pawlean) · 2025-06-20 Hey, Justin! Welcome :slight_smile: What are you building? 👀 Your approach is looking great so far — you’ve got the key pieces down: using `Promise.allSettled()` for concurrent uploads, tracking individual progress with `onUploadProgress`, and managing state cleanly for each file. A couple of ideas that could make it even more robust: **Error handling**: You could add retry logic for any failed uploads. Something like: ```js const uploadWithRetry = async (file, maxRetries = 3) => { for (let attempt = 1; attempt <= maxRetries; attempt++) { try { return await upload(file.name, file, options); } catch (error) { if (attempt === maxRetries) throw error; await new Promise(resolve => setTimeout(resolve, 1000 * attempt)); } } }; ``` **Performance**: If you're uploading lots of files, it might help to limit how many go through at once. For example: ```js const batchSize = 3; for (let i = 0; i < files.length; i += batchSize) { const batch = files.slice(i, i + batchSize); await Promise.allSettled(batch.map(uploadFile)); } ``` **Cleanup tip**: Make sure you're handling component unmounts properly to avoid any memory leaks. You’re on the right track! We don’t have a Vercel example for this exact use case, but what you’ve built aligns well with React patterns. Keep going! This is shaping up nicely. If you'd like to contribute one, we'd always welcome them :slight_smile: