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,
});
}
}
}