How to Download Files With JavaScript

Stan Georgian
ITNEXT
Published in
6 min readApr 26, 2021

--

Photo by Pankaj Patel on Unsplash

Downloading files is an essential aspect of surfing the internet. Tons of files are downloaded from the internet every day, from binary files (such as applications, images, videos, and audio) to plain text files.

If you have a web developer and you want to add this feature to your application, here is how you can do it.

We will inspect 3 different approaches:

  • basic mode using only HTML elements;
  • using JavaScript with Fetch API and HTML elements;
  • using XMLHttpRequest and HTML elements, but in a more complex scenario in which we implement a system to measure progress;

Method I

The first and the simplest method implies creating an anchor HTML element that has the download attribute.

By definition, the download attribute specifies that the target (the file specified in the href attribute) will be downloaded when a user clicks on the hyperlink.

Also with this download attribute we can specify the new name of the file after it is downloaded. Therefore if we want to download the file with a specific name, we can control this using this attribute. However, the user will still be able to change the name when the native download window appears, but the name we provided will be the default.

If the value is omitted, the original filename is used.

RAW

This method is great when we don’t need to do any action based on this download process.

At the same time, we can use this method even though we can’t render the anchor HTML element, using JavaScript.

RAW

The function above is doing just the same, just that we create the anchor HTML Element on the fly, only for this download action and then we remove it.

  • IMG_URL is the URL of the image we want to download;
  • FILE_NAME is the new name of the file after it is downloaded;

The limitation of this method is that it must respect the same-origin policy, thus this attribute works properly for same-origin URLs.

A common scenario is when you want to download an image from another server and instead of downloading it, the browser will open it in a new tab.

The key aspect of this method is that the download process will start automatically and can be viewed natively in the browser.

Notice in the image above how the download process was sent to the browser to manage it, and the browser provides control over it and shows progress.

Method II

The second method and the third method use the same technique with the anchor element, but instead of supplying the image URL, we convert the file’s content to a Blob and then we create DOMString from it using the createObjectURL method.

RAW

Notice that at the end we have used URL.revokeObjectURL , which is important in terms of memory management. When using URL.createObjectURL a new object URL is created, even if it is called with the same blob object.

Whenever an object URL is created, it stays around for the lifetime of the document on which it was created. The browser will release all object URLs when the document is being unloaded. However, it is important that you release object URLs whenever they are no longer needed in order to improve performance and minimize memory usage.

The key aspect of this method is that the download process will start automatically, but within our application and will be passed to the browser only when the download is complete.

Notice in the GIF above that once we click the Download button, nothing seems to happen, because the download takes place as an asynchronous task in our application and once it is completed, it will be passed to the browser.

Once that browser window appears and we click save, the file is automatically saved on our computer.

With this method now we are able to download any type of file regardless of the origin server. However, the problem is that because the download takes place inside our application, the user may think that nothing happened when he clicked and therefore it is up to us to manage large file downloads by implementing the measurement of progress.

At the same time, this method is useful when we need to perform certain actions inside our application once the file has completed downloaded. Show a message, send a request to the back-end render a new page, and so on…

Method III

The third method is similar to the second method, we are still going to use Blob and createObjectURL, but instead of using the Fetch API, we will use XMLHttpRequest.

We are using XMLHttpRequest over Fetch because at the moment speaking Fetch API doesn’t provide an interface for progress measurement, while XMLHttpRequest does.

RAW

The beginning and the onreadystatechange block is similar to the second function. Download the response as a Blob object, create a DOMString, and use an anchor element to download the file.

Insideonprogress we use e.loaded and e.total values to calculate the progress in percentages and the elapsed time, as well as the download speed and the remaining time.

Notice in the GIF above that we have the same behavior as for the second method, only now we can monitor progress. After the file is completely downloaded, it will be sent to the browser and then it will be instantly saved to disk.

Wrap up

Each of the above methods represents an update over the previous method.

The first method is the easiest. In this, we simply forward the download process to the browser to manage it natively. This method is the preferred way when the application does not have to perform certain actions based on the load state.

In the second, we manage the download internally and send it to the browser only when the download is complete. In this way, we can control the download inside the application and we can react depending on its status. This method works well for small files that are downloaded quickly, but when the file is too large, the user may think that the application is faulty, if nothing happens on the UI to indicate to the user that a download is in progress.

In the last method, we implement our own measurement of progress, which is similar to that in the browser.

--

--