How to Download Any File In JavaScript

How to Download Any File In JavaScript

Downloading programmatically generated and CDN hosted files
Ferenc Almasi • 2022 November 03 • šŸ“– 5 min read

In order to download any kind of file programmatically in JavaScript, we can use an invisible anchor with aĀ downloadĀ attribute. When theĀ downloadĀ attribute is set on an anchor, it will try to download the resource at theĀ hrefĀ attribute.

<!-- Using the original name for the downloaded file -->
<a href="/resources/report.pdf" download>

<!-- Using a custom name for the downloaded file -->
<a href="/resources/report.pdf" download="latest-reports.pdf">
Anchors with a download attribute
Copied to clipboard!

By setting a value for theĀ downloadĀ attribute, we can specify a custom name for the downloaded file.

Of course, when we want to programmatically generate the file to be downloaded on the fly, we don't have it available on the server, so there's no URL to point the anchor to. To generate and download the file programmatically, we can use data URLs.

What are Data URLs

Data URLs are URLs prefixed with theĀ data:Ā scheme that allows us to inline small files into documents. We are going to use this approach to programmatically generate the resource that we want to download, in this example, a JSON file containing the necessary data. A data URL has the following format:

data:[<mediatype>][;base64],<data>
The format of a data URL
Copied to clipboard!
  • TheĀ mediatypeĀ is a MIME type, such asĀ image/jpegĀ orĀ text/html. In our case, we will be usingĀ text/plainĀ for plain text files. We are also going to need to set the character encoding to UTF-8 for the correct encoding format.
  • There is an optionalĀ base64Ā string we can set in case we want to embed base64-encoded binary data. In our case, we can omit this value.
  • Lastly, we have the actual data for the file. To convert the data into the correct URI string, we can use the built-inĀ encodeURIComponentĀ function.

This leaves us with the following for the data URL:

'data:text/plain;charset=utf-8,' + encodeURIComponent(data)
Data URI needed for exporting data in JSON format
Copied to clipboard!
Looking to improve your skills? Check out our interactive course to master JavaScript from start to finish.
Master JavaScript

Dynamically Creating a Download Link

In order to use our Data URL, we also need to dynamically create a link. For this, we can use document.createElement. This will create an anchor for us, on which we can set the href and download attributes accordingly, and then programmatically click on the link in order to trigger a download. With everything combined, we can use the following function to download a programmatically generated JSON file.

const download = (data, filename) => {
    const data = JSON.stringify(data)
    const link = document.createElement('a')

    link.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(data))
    link.setAttribute('download', filename || 'data.json')
    link.style.display = 'none'

    document.body.appendChild(link)

    link.click()

    document.body.removeChild(link)
}

// Later call it like so:
download({ name: 'John Doe', email: '[email protected]', phone: '+1 234 567' })

// Calling with a custom file name
download({ name: 'John Doe' }, 'user.json')
download.js Creating the download functionality for downloading files
Copied to clipboard!

This function accepts a JavaScript object that will be converted into JSON. It can also optionally accept a filename as the second parameter. When the link is created, we canĀ set the appropriate attributes on it using theĀ setAttributeĀ method. We also want to set itsĀ displayĀ property toĀ none, in order to prevent the link from showing up anywhere on the page.

After all necessary attributes are present on the link, we can append the element to the document, using theĀ appendChildĀ method, and trigger a click on the link to initiate the download. After the download of the resource has been started, we can remove the link from the document using theĀ removeChildĀ method.


How to Download Blobs in JavaScript

The above method, however, is limited. It doesn't work with non-text-based files, and while we could change the MIME type, it also doesn't work with files hosted elsewhere. In order to come around this, introduce you to blobs.

Using blobs is a more generic approach to download binary files, or files that are not programmatically generated, but hosted elsewhere. For this, we need to use the fetch API in combination with the URL.createObjectURL to create the correct URL for the blob, then use this for the href. Based on this, our code changes to the following:

const download = async (url, filename) => {
    const data = await fetch(url)
    const blob = await data.blob()
    const objectUrl = URL.createObjectURL(blob)

    const link = document.createElement('a')

    link.setAttribute('href', objectUrl)
    link.setAttribute('download', filename)
    link.style.display = 'none'

    document.body.appendChild(link)
  
    link.click()
  
    document.body.removeChild(link)
}

// Later call it with an URL and filename like so:
download('https://unpkg.com/[email protected]/umd/react.production.min.js', 'react.js')
Creating the download functionality for downloading blobs
Copied to clipboard!

In the above example, we are using async/await to fetch the resource at the provided URL. We can then transform the returned result by using the blob method on it. Lastly, we then generate the proper blob URL using URL.createObjectURL which expects a blob to be passed for it.

// The returned value of a blob
> Blob { size: 10737, type: 'application/javascript' }

// The returned value of a blob URL
> 'blob:http://localhost:8080/b813048a-2074-4333-ac10-0b81b9c5ca17'
The value of a blob and a blob URL
Copied to clipboard!
Looking to improve your skills? Check out our interactive course to master JavaScript from start to finish.
Master JavaScript

In Conclusion

In conclusion, we can either use a data URL to download dynamically generated files on the fly or use the fetch API with URL.createObjectURL to download blobs and files from other domains. Do you also need to read back files in JavaScript and monitor their progress? Check out our tutorial below.

How to Open Any File in Javascript with Progressbar
Did you find this page helpful?
šŸ“š More Webtips
Frontend Course Dashboard
Master the Art of Frontend
  • check Unlimited access to hundred of tutorials
  • check Access to exclusive interactive lessons
  • check Remove ads to learn without distractions
Become a Pro

Recommended