Introduction
I was developing an app using React to download Qiita posts retrieved from the Qiita API as .md files.
However, I ran into a problem: "Even though I checked multiple posts and attempted to download them all at once, only one was downloaded."
In this article, I'll explain the actual symptoms and share the root cause of why only one post was downloaded.
Cause
In conclusion, the problem was caused by calling URL.revokeObjectURL(url) too quickly.
The bulk download process can be summarized as follows:
Create a Blob from the article text (a Blob is a container for storing data, a mechanism for manipulating file contents with JavaScript).
Create a "temporary URL" using URL.createObjectURL(blob). (URL.createObjectURL(blob) is a function that automatically generates a temporary URL for accessing a Blob.)
Start the download using a.href = url → click().
When you're done using it, destroy it using URL.revokeObjectURL(url).
(URL.revokeObjectURL(url) is a function that deletes the temporary URL.)
The problem lies in the following code.
const url = URL.createObjectURL(blob);
a.href = url;
a.click();
URL.revokeObjectURL(url); // ← This was called immediately.
Because the browser discarded the URL before the download had finished,
the first URL worked, but the second and subsequent URLs became invalid, resulting in only one URL crashing.
Solution
I fixed the issue by calling URL.revokeObjectURL(url) with a slight delay.
The final code that worked reliably
const handleDownload = (title: string, body: string) => {
const blob = new Blob([body], { type: "text/markdown" });
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = `${title}.md`;
a.click();
/ Immediately abandoning the download will break → Wait a bit
setTimeout(() => URL.revokeObjectURL(url), 100);
};
Even when checking multiple articles and downloading them all at once, they are all saved correctly.
Summary
Multiple downloads work reliably with appropriate delays.
Top comments (0)