Force Download with JavaScript
Force download scripts have been an important part of internet usability for a long time. I can attest to that by the number of times I've implemented this feature on the server side and the popularity of my PHP Force Download post, even to this day. With the web world having moved much more the client side, I started looking for a method to force download without the need of a server, and I found it....right in the Firefox DevTools Debugger!
The JavaScript
The function to do this is quite small and relies on URL.createObjectUrl
:
function downloadFile(data, fileName, type="text/plain") { // Create an invisible A element const a = document.createElement("a"); a.style.display = "none"; document.body.appendChild(a); // Set the HREF to a Blob representation of the data to be downloaded a.href = window.URL.createObjectURL( new Blob([data], { type }) ); // Use download attribute to set set desired file name a.setAttribute("download", fileName); // Trigger the download by simulating click a.click(); // Cleanup window.URL.revokeObjectURL(a.href); document.body.removeChild(a); }
The function injects an <a>
element into the body, sets it URL to a Blob
value to the text content of the destination file, and clicks the element to trigger the download. The element remains hidden during the process and is removed from the DOM immediately after the click()
call. As soon as the function is called, the browser's download prompt is displayed.
I look forward to learning more about both createObjectURL
and Blob
; those two are the true magic of this technique!
Shout out to Sneha Jain for implementing this great technique within the Firefox DevTools debugger!
Typo
{type}
should be replaced by{type: type}
. Ex:{type: "text/plain;charset=utf-8"}
{ type }
is acting exactly like{ type : type}
Quite nice and concise. This works with generating a text file and downloading it: What’s the magic to fetch a remote text file not even on my server and handing it back to the browser for download? I want to avoid streaming through php.. In my case they are small enough that maybe I could stream thru js?
Ah ha! It is possible! Preceding Dave Walsh’s script above, I first stream a fetch of the file (remote or “local” on the server) with
fetch()
like:Then I pass fileContents into the function in this solution as
data
. I don’t know if this is the best way, but it seems to be working great in my testing.