how to download file in react js

JavascriptReactjsDownload

Javascript Problem Overview


I receive file url as response from api. when user clicks on download button, the file should be downloaded without opening file preview in a new tab. How to achieve this in react js?

Javascript Solutions


Solution 1 - Javascript

This is not related to React. However, you can use the download attribute on the anchor <a> element to tell the browser to download the file.

<a href='/somefile.txt' download>Click to download</a>

This is not supported on all browsers: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a

Solution 2 - Javascript

If you are using React Router, use this:

<Link to="/files/myfile.pdf" target="_blank" download>Download</Link>

Where /files/myfile.pdf is inside your public folder.

Solution 3 - Javascript

Triggering browser download from the frontend is not reliable.

What you should do is, create an endpoint on a server that when called, responds with the correct response headers, thus triggering the browser download.

Frontend code can only do so much. The 'download' attribute for example, might just open the file in a new tab depending on the browser and the type of the file.

The response headers you need to look at are Content-Type and Content-Disposition. You should check this answer for a more detailed explanation on those headers.

Solution 4 - Javascript

tldr; fetch the file from the url, store it as a local Blob, inject a link element into the DOM, and click it to download the Blob

I had a PDF file that was stored in S3 behind a Cloudfront URL. I wanted the user to be able to click a button and immediately initiate a download without popping open a new tab with a PDF preview. Generally, if a file is hosted at a URL that has a different domain that the site the user is currently on, immediate downloads are blocked by many browsers for user security reasons. If you use this solution, do not initiate the file download unless a user clicks on a button to intentionally download.

In order to get by this, I needed to fetch the file from the URL getting around any CORS policies to save a local Blob that would then be the source of the downloaded file. In the code below, make sure you swap in your own fileURL, Content-Type, and FileName.

fetch('https://cors-anywhere.herokuapp.com/' + fileURL, {
    method: 'GET',
    headers: {
      'Content-Type': 'application/pdf',
    },
  })
  .then((response) => response.blob())
  .then((blob) => {
    // Create blob link to download
    const url = window.URL.createObjectURL(
      new Blob([blob]),
    );
    const link = document.createElement('a');
    link.href = url;
    link.setAttribute(
      'download',
      `FileName.pdf`,
    );

    // Append to html link element page
    document.body.appendChild(link);

    // Start download
    link.click();

    // Clean up and remove the link
    link.parentNode.removeChild(link);
  });

This solution references solutions to getting a blob from a URL and using a CORS proxy.

Update As of January 31st, 2021, the cors-anywhere demo hosted on Heroku servers will only allow limited use for testing purposes and cannot be used for production applications. You will have to host your own cors-anywhere server by following cors-anywhere or cors-server.

Solution 5 - Javascript

browsers are smart enough to detect the link and downloading it directly when clicking on an anchor tag without using the download attribute.

after getting your file link from the api, just use plain javascript by creating anchor tag and delete it after clicking on it dynamically immediately on the fly.

const link = document.createElement('a');
link.href = `your_link.pdf`;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);

Solution 6 - Javascript

This is how I did it in React:

import MyPDF from '../path/to/file.pdf';
<a href={myPDF} download="My_File.pdf"> Download Here </a>

It's important to override the default file name with download="name_of_file_you_want.pdf" or else the file will get a hash number attached to it when you download.

Solution 7 - Javascript

Solution (Work Perfect for React JS, Next JS)

You can use js-file-download and this is my example:

import axios from 'axios'
import fileDownload from 'js-file-download'
 
...

handleDownload = (url, filename) => {
  axios.get(url, {
    responseType: 'blob',
  })
  .then((res) => {
    fileDownload(res.data, filename)
  })
}
 
...

<button onClick={() => {this.handleDownload('https://your-website.com/your-image.jpg', 'test-download.jpg')
}}>Download Image</button>

This plugin can download excel and other file types.

Solution 8 - Javascript

React gives a security issue when using a tag with target="_blank".

I managed to get it working like that:

<a href={uploadedFileLink} target="_blank" rel="noopener noreferrer" download>
   <Button>
      <i className="fas fa-download"/>
      Download File
   </Button>
</a>

Solution 9 - Javascript

fetchFile(){
  axios({
        url: `/someurl/thefiles/${this.props.file.id}`,
        method: "GET",
        headers: headers,
        responseType: "blob" // important
    }).then(response => {
        const url = window.URL.createObjectURL(new Blob([response.data]));
        const link = document.createElement("a");
        link.href = url;
        link.setAttribute(
            "download",
            `${this.props.file.name}.${this.props.file.mime}`
        );
        document.body.appendChild(link);
        link.click();

        // Clean up and remove the link
        link.parentNode.removeChild(link);
    });
}
render(){
  return( <button onClick={this.fetchFile}> Download file </button>)
}

Solution 10 - Javascript

You can use FileSaver.js to achieve this goal:

const saveFile = () => {
fileSaver.saveAs(
  process.env.REACT_APP_CLIENT_URL + "/resources/cv.pdf",
  "MyCV.pdf"
);

};

<button className="cv" onClick={saveFile}>
    Download File
</button>

Solution 11 - Javascript

import resume from '../assets/data/resume.pdf';

<a href={resume} download="YourName resume.pdf"> Download CV </a>

Solution 12 - Javascript

I have the exact same problem, and here is the solution I make use of now: (Note, this seems ideal to me because it keeps the files closely tied to the SinglePageApplication React app, that loads from Amazon S3. So, it's like storing on S3, and in an application, that knows where it is in S3, relatively speaking.

Steps

3 steps:

  1. Make use of file saver in project: npmjs/package/file-saver (npm install file-saver or something)
  2. Place the file in your project You say it's in the components folder. Well, chances are if you've got web-pack it's going to try and minify it.(someone please pinpoint what webpack would do with an asset file in components folder), and so I don't think it's what you'd want. So, I suggest to place the asset into the public folder, under a resource or an asset name. Webpack doesn't touch the public folder and index.html and your resources get copied over in production build as is, where you may refer them as shown in next step.
  3. Refer to the file in your project Sample code:
    import FileSaver from 'file-saver';
    FileSaver.saveAs(
        process.env.PUBLIC_URL + "/resource/file.anyType",
        "fileNameYouWishCustomerToDownLoadAs.anyType");
    
Source
Appendix

Solution 13 - Javascript

You can define a component and use it wherever.

import React from 'react';
import PropTypes from 'prop-types';


export const DownloadLink = ({ to, children, ...rest }) => {

  return (
    <a
      {...rest}
      href={to}
      download
    >
      {children}
    </a>
  );
};


DownloadLink.propTypes = {
  to: PropTypes.string,
  children: PropTypes.any,
};

export default DownloadLink;

Solution 14 - Javascript

The package that solved my download link issue was:

> npm install --save react-download-link

Use it like this:

fileDownload(axiosResponse.data, 'filename.csv');

You can create e.g. a C# Web API Endpoint like this on the backend side:

[HttpGet("GenerateSitemap")]
public async Task<IActionResult> GenerateSitemap()
{
    var sitemapString = "[place-xml-sitemap-string-here]";
    var serializedObj = JsonConvert.SerializeObject(obj);
    var bytesObj = Encoding.UTF8.GetBytes(serializedObj);

    return File(sitemapString.SerializeToByteArray(), "application/octet-stream");
}

Solution 15 - Javascript

Great and fast solution:

window.open('https://myapi.com/download/file-name')

Solution 16 - Javascript

We can user react-download-link component to download content as File.

<DownloadLink
label="Download"
filename="fileName.txt"
exportFile={() => "Client side cache data here…"}/>

https://frugalisminds.com/how-to-download-file-in-react-js-react-download-link/

Solution 17 - Javascript

Download file

For downloading you can use multiple ways as been explained above, moreover I will also provide my strategy for this scenario.

  1. npm install --save react-download-link
  2. import DownloadLink from "react-download-link";
  3. React download link for client side cache data
    <DownloadLink 
        label="Download" 
        filename="fileName.txt"
        exportFile={() => "Client side cache data here…"}
    />
    
  4. Download link for client side cache data with Promises
    <DownloadLink
        label="Download with Promise"
        filename="fileName.txt"
        exportFile={() => Promise.resolve("cached data here …")}
    />
    
  5. Download link for data from URL with Promises Function to Fetch data from URL
     getDataFromURL = (url) => new Promise((resolve, reject) => {
        setTimeout(() => {
            fetch(url)
                .then(response => response.text())
                .then(data => {
                    resolve(data)
                });
        });
    }, 2000);
    
  6. DownloadLink component calling Fetch function
    <DownloadLink
          label=”Download”
          filename=”filename.txt”
          exportFile={() => Promise.resolve(this. getDataFromURL (url))}
    />
    

Happy coding! ;)

Solution 18 - Javascript

I have tried this DownloadLink, it is fetching the data from API which I can see using dev tools but it is not trigerring file download. any idea if I am missing anything ?

This is what I have used -

getDataFromURL = (url) => new Promise((resolve, reject) => {
setTimeout(() => {
    fetch(url)
        .then(response => response.text())
        .then(data => {
            resolve(data)
        });
});

});

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSameer ThiteView Question on Stackoverflow
Solution 1 - JavascriptlippView Answer on Stackoverflow
Solution 2 - JavascriptJavier LópezView Answer on Stackoverflow
Solution 3 - JavascriptJackyefView Answer on Stackoverflow
Solution 4 - JavascriptBrian LiView Answer on Stackoverflow
Solution 5 - JavascriptMuhoView Answer on Stackoverflow
Solution 6 - JavascriptKevinView Answer on Stackoverflow
Solution 7 - JavascriptC Plus AKView Answer on Stackoverflow
Solution 8 - JavascriptdodobratView Answer on Stackoverflow
Solution 9 - JavascriptOtabek ButcherView Answer on Stackoverflow
Solution 10 - JavascriptalshafiView Answer on Stackoverflow
Solution 11 - JavascriptSuprabhat KumarView Answer on Stackoverflow
Solution 12 - JavascriptRohan KumarView Answer on Stackoverflow
Solution 13 - JavascriptHamid ShojaView Answer on Stackoverflow
Solution 14 - JavascriptCodingYourLifeView Answer on Stackoverflow
Solution 15 - JavascriptjoaocarlospfView Answer on Stackoverflow
Solution 16 - JavascriptAsha GadadView Answer on Stackoverflow
Solution 17 - JavascriptOtabek ButcherView Answer on Stackoverflow
Solution 18 - JavascriptDIIDView Answer on Stackoverflow