乐闻世界logo
搜索文章和话题

How to download files using axios

4个答案

1
2
3
4

When using Axios for file downloads, it is essential to set the appropriate response type and process the returned data to facilitate the download. Here is a step-by-step guide on using Axios for file downloads:

  1. Configure the Axios request to handle Blob data: To download a file, receive data as a blob. When sending the request, set Axios's responseType to 'blob'.

  2. Send a GET request: The GET request sent to the file's location retrieves the file content.

  3. Process the response and create a download link: Once the response is received, use the URL.createObjectURL() method to generate a URL pointing to the blob.

  4. Trigger the file download: Create an <a> tag, set its href to the previously created blob URL, and set the download attribute to specify the filename. Then, programmatically trigger the click event to initiate the download.

  5. Cleanup: After the download is complete, revoke the object URL to free browser resources.

Here is a specific code example:

javascript
import axios from 'axios'; function downloadFile(url, filename) { axios({ url: url, // file URL method: 'GET', responseType: 'blob', // critical }).then((response) => { // create a link element const link = document.createElement('a'); // create the download link link.href = window.URL.createObjectURL(new Blob([response.data])); // set the filename for download link.setAttribute('download', filename); // hide the element link.style.visibility = 'hidden'; // append the link to the DOM document.body.appendChild(link); // trigger click link.click(); // remove the link element document.body.removeChild(link); // revoke the URL object window.URL.revokeObjectURL(link.href); }).catch((error) => console.error('File download failed:', error)); } // call the function to download the file downloadFile('https://example.com/somefile.pdf', 'myFile.pdf');

In this example, the downloadFile function accepts the file URL and desired filename as parameters. It uses Axios to send a GET request with responseType set to blob. Upon receiving the response, it creates an invisible <a> tag to trigger the download. Finally, it ensures the blob URL is revoked after completion.

2024年6月29日 12:07 回复

When you want to download files using Axios and certain security measures, it becomes more complex. To save others from spending excessive time solving this issue, let me guide you through the process.

You need to do three things:

  1. Configure your server to allow the browser to access the necessary HTTP headers.
  2. Implement server-side services to correctly announce the file type for download.
  3. Implement an Axios handler to trigger the File Download dialog box in the browser.

These steps are generally feasible, but they become quite complex due to browser and CORS relationships. Let's go step by step:

  1. Configure your (HTTP) server

When using transport security, JavaScript executed in the browser [by design] can only access the 6 HTTP headers actually sent by the HTTP server. If we want the server to suggest the filename for download, we must notify the browser to grant JavaScript access to other headers that convey the suggested filename.

For discussion purposes, let's assume the server transmits the suggested filename in the X-Suggested-Filename HTTP header. The HTTP server tells the browser to expose the custom header to JavaScript/Axios, as follows:

shell
Access-Control-Expose-Headers: X-Suggested-Filename

The exact method to configure the HTTP server to set this header varies by product.

For a complete explanation and details of these standard headers, please refer to https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers.

  1. Implement server-side services

Your server-side service implementation must now perform two tasks:

  1. Create the (binary) document and assign the correct Content-Type to the response.
  2. Assign a custom header containing the client-suggested filename (X-Suggested-Filename).

Depending on your chosen technology stack, this can be done in different ways. I'll use JavaEE 7 standard to illustrate an example that generates an Excel report:

shell
@GET @Path("/report/excel") @Produces("application/vnd.ms-excel") public Response getAllergyAndPreferencesReport() { // Create the document to be downloaded final byte[] theDocumentData = .... // Define a suggested filename final String filename = ... // Create the JAXRS response // Don't forget to include the filename in 2 HTTP headers: // // a) The standard 'Content-Disposition' one, and // b) The custom 'X-Suggested-Filename' // final Response.ResponseBuilder builder = Response.ok( theDocumentData, "application/vnd.ms-excel") .header("X-Suggested-Filename", fileName); builder.header("Content-Disposition", "attachment; filename=" + fileName); // All Done. return builder.build(); }

This service now sends the binary document (in this case, an Excel report), sets the correct content type, and also sends a custom HTTP header containing the suggested filename for saving the document.

  1. Implement an Axios handler for the received document

There are some pitfalls, so let's ensure all details are correctly configured:

  1. The service responds to GET (i.e., HTTP GET), so the axios call must be 'axios.get(...)'.
  2. The document is transmitted as a byte stream, so you must instruct Axios to treat the response as an HTML5 Blob (i.e., set responseType: 'blob').
  3. In this example, the FileSaver library is used to trigger the browser dialog box. However, you can choose another.

The Axios implementation would be similar to:

shell
// Fetch the dynamically generated excel document from the server. axios.get(resource, {responseType: 'blob'}).then((response) => { // Log somewhat to show that the browser actually exposes the custom HTTP header const fileNameHeader = "x-suggested-filename"; const suggestedFileName = response.headers[fileNameHeader]; const effectiveFileName = (suggestedFileName === undefined ? "allergierOchPreferenser.xls" : suggestedFileName); console.log(`Received header [${fileNameHeader}]: ${suggestedFileName}, effective fileName: ${effectiveFileName}`); // Let the user save the file. FileSaver.saveAs(response.data, effectiveFileName); }).catch((response) => { console.error("Could not Download the Excel report from the backend.", response); });

2024年6月29日 12:07 回复

When the response contains a downloadable file, the response headers will resemble:

shell
Content-Disposition: "attachment;filename=report.xls" Content-Type: "application/octet-stream" // or Content-type: "application/vnd.ms-excel"

You can create a separate component that includes a hidden iframe.

javascript
import * as React from 'react'; var MyIframe = React.createClass({ render: function() { return ( <div style={{display: 'none'}}> <iframe src={this.props.iframeSrc} /> </div> ); } });

Now, you can pass the URL of the downloadable file as a prop to this component, causing it to re-render and download the file upon receiving the prop.

Edit:

You can also use the js-file-download module. Link to GitHub repository

javascript
const FileDownload = require('js-file-download'); Axios({ url: 'http://localhost/downloadFile', method: 'GET', responseType: 'blob', // Important }).then((response) => { FileDownload(response.data, 'report.csv'); });
2024年6月29日 12:07 回复
  1. Use Axios to download files with responseType: 'blob'.
  2. Create a file link using the blob from the Axios/Server response.
  3. Create an <a> HTML element whose href points to the file link created in step 2 and click it.
  4. Clean up dynamically created file links and HTML elements.
javascript
axios({ url: 'http://api.dev/file-download', // your URL method: 'GET', responseType: 'blob', // important }).then((response) => { // Create file link in browser's memory const href = URL.createObjectURL(response.data); // Create "a" HTML element with href to file & click const link = document.createElement('a'); link.href = href; link.setAttribute('download', 'file.pdf'); // or any other extension document.body.appendChild(link); link.click(); // Clean up "a" element & remove ObjectURL document.body.removeChild(link); URL.revokeObjectURL(href); });

See the example https://gist.github.com/javilobo8/097c30a233786be52070986d8cdb1743

Full credit: https://gist.github.com/javilobo8

MDN provides more documentation on URL.createObjectURL and URL.revokeObjectURL. Releasing the object is crucial for preventing memory leaks. In the above function, since the file has been downloaded, we can immediately revoke the object.

Every time you call createObjectURL(), a new object URL is created, even if you've already created one for the same object. When you no longer need them, you must release them by calling URL.revokeObjectURL() for each one.

When the document is unloaded, the browser automatically releases object URLs; however, for optimal performance and memory usage, it is recommended to explicitly release them if there is a safe time to do so.

2024年6月29日 12:07 回复

你的答案