Skip to main content

How to Download Files with Axios in JavaScript

A common requirement in web applications is to allow users to download files—such as PDFs, images, or CSVs—by clicking a button. When these files need to be fetched from an API, Axios is an excellent tool for the job.

This guide will teach you the modern, standard method for downloading files with Axios. You will learn how to create a reusable async function that fetches a file as a Blob, programmatically triggers a download in the browser, and correctly names the downloaded file.

The Core Logic: Fetching a Blob and Simulating a Click

You cannot directly "save" a file from an Axios response. Instead, you must trigger a download in the browser by simulating a click on a temporary anchor (<a>) tag.

  1. Fetch the File as a Blob: Make a GET request with Axios, setting the responseType to 'blob'. A Blob is a file-like object of immutable, raw data.
  2. Create an Object URL: Use URL.createObjectURL(blob) to create a temporary, in-memory URL for the downloaded data.
  3. Create and Click a Link: Create an <a> element, set its href to the object URL, add the download attribute to specify the filename, and programmatically click it.
  4. Clean Up: Revoke the object URL to free up browser memory.

The Modern Solution: A Reusable async Download Function

The best practice is to encapsulate this logic into a single, reusable async function.

The Reusable Function:

import axios from 'axios';

/**
* Downloads a file from a URL using Axios.
* @param {string} url The URL of the file to download.
* @param {string} [defaultFilename] The default filename if not provided by the server.
*/
async function downloadFile(url, defaultFilename = 'downloaded-file') {
try {
// 1. Fetch the file as a blob
const response = await axios.get(url, {
responseType: 'blob',
});

// 2. Create an object URL
const objectUrl = window.URL.createObjectURL(response.data);

// 3. Create and click the link
const link = document.createElement('a');
link.href = objectUrl;
link.download = defaultFilename; // A fallback filename

// Try to get the filename from the Content-Disposition header
const disposition = response.headers['content-disposition'];
if (disposition) {
const filenameMatch = disposition.match(/filename="?(.+)"?/i);
if (filenameMatch && filenameMatch[1]) {
link.download = filenameMatch[1];
}
}

document.body.appendChild(link);
link.click();

// 4. Clean up
document.body.removeChild(link);
window.URL.revokeObjectURL(objectUrl);

} catch (error) {
console.error('There was an error downloading the file:', error);
}
}

Practical Example: Downloading a File on Button Click

With our downloadFile utility function, triggering a download from a user event becomes simple and readable.

<button id="download-btn">Download PDF</button>

Solution:

const downloadButton = document.getElementById('download-btn');
const fileUrl = 'http://localhost:3000/example-file.pdf';

downloadButton.addEventListener('click', () => {
console.log('Starting download...');
downloadFile(fileUrl, 'my-custom-name.pdf');
});

A Note on Filenames and the Content-Disposition Header

How does the browser know what to name the downloaded file?

  • The download attribute: The value you provide to the <a> tag's download attribute is a suggestion to the browser for the filename.
  • The Content-Disposition header: For a more robust solution, the server should send a Content-Disposition response header. This header explicitly tells the browser that the response is an attachment and provides a filename.
    Content-Disposition: attachment; filename="report-2023-10-27.pdf"

Our reusable function prioritizes the Content-Disposition header if it exists but falls back to the defaultFilename you provide.

A Critical Note on CORS

This fetch-based approach is subject to Cross-Origin Resource Sharing (CORS) policies.

  • If you are downloading a file from a different domain than your website, that server must be configured to allow your domain to make requests.
  • If the server does not send the correct Access-Control-Allow-Origin header, the Axios request will fail, and you will see a CORS error in the console. You cannot bypass this from the client-side.

Conclusion

Downloading files with Axios is a multi-step process that is best handled by a clean, reusable function.

  • The key is to set the responseType: 'blob' in your Axios request config.
  • You must then create an object URL from the blob and use a temporary <a> tag with the download attribute to programmatically trigger the download.
  • For robust filename handling, your server should send a Content-Disposition header.
  • Remember that this method is always subject to browser CORS policies when requesting files from a different domain.