10

I want to try to download an image by clicking on a button, but when I click on the button, it is not downloading the image, but it is directly opening the image. But I want to download the image, so how can I download the image in React?

<a
  href="https://timesofindia.indiatimes.com/thumb/msid-70238371,imgsize-89579,width-400,resizemode-4/70238371.jpg"
  download
>
  <i className="fa fa-download" />
</a>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Dharmesh
  • 5,383
  • 17
  • 46
  • 62

6 Answers6

20

I came across this SO question trying to figure out how to download a PNG image and found that Shubham Verma's answer didn't quite do it for me as the downloaded file couldn't be opened. I needed to use arraybuffer to convert the image.

Here's the code that worked.

function App() {
  const download = e => {
    console.log(e.target.href);
    fetch(e.target.href, {
      method: "GET",
      headers: {}
    })
      .then(response => {
        response.arrayBuffer().then(function(buffer) {
          const url = window.URL.createObjectURL(new Blob([buffer]));
          const link = document.createElement("a");
          link.href = url;
          link.setAttribute("download", "image.png"); //or any other extension
          document.body.appendChild(link);
          link.click();
        });
      })
      .catch(err => {
        console.log(err);
      });
  };
  return (
    <div className="App">
      <a
        href="https://upload.wikimedia.org/wikipedia/en/6/6b/Hello_Web_Series_%28Wordmark%29_Logo.png"
        download
        onClick={e => download(e)}
      >
        <i className="fa fa-download" />
        download
      </a>
    </div>
  );
}

Codesandbox: https://codesandbox.io/s/dreamy-gould-h1l72

P.S.: The download approach was taken from the following answer, but I used plain fetch instead of Axios. Download binary file with Axios

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
alanmynah
  • 241
  • 2
  • 11
17

Install file-saver package:

npm i file-saver

Your React component:

  import { saveAs } from 'file-saver'

  const Index = () => {
    const downloadImage = () => {
      saveAs('image_url', 'image.jpg') // Put your image URL here.
    }

    return <Button onClick={downloadImage}>Download!</Button>
  }
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ibad Shaikh
  • 2,704
  • 3
  • 15
  • 27
8

You can do something like this:

function App() {
  const download = () => {
    var element = document.createElement("a");
    var file = new Blob(
      [
        "https://timesofindia.indiatimes.com/thumb/msid-70238371,imgsize-89579,width-400,resizemode-4/70238371.jpg"
      ],
      { type: "image/*" }
    );
    element.href = URL.createObjectURL(file);
    element.download = "image.jpg";
    element.click();
  };
  return (
    <div className="App">
      <a
        href="https://timesofindia.indiatimes.com/thumb/msid-70238371,imgsize-89579,width-400,resizemode-4/70238371.jpg"
        download
        onClick={() => download()}
      >
        <i className="fa fa-download" />
        download
      </a>
    </div>
  );
}

Here is a working URL: https://codesandbox.io/s/clever-noether-3nu2p?fontsize=14

Note: More things can be done. I have just created this for demo purposes.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Shubham Verma
  • 4,918
  • 1
  • 9
  • 22
0

Here is an example to download an image with a URL and dynamic name.

const download = async() => {
    const originalImage = "https://cdn1.iconfinder.com/data/icons/ninja-things-1/1772/ninja-simple-512.png";
    const image = await fetch(originalImage);

    // Split image name
    const nameSplit = originalImage.split("/");
    const  duplicateName = nameSplit.pop();

    const imageBlog = await image.blob()
    const imageURL = URL.createObjectURL(imageBlog)
    const link = document.createElement('a')
    link.href = imageURL;
    link.download = "" + duplicateName + "";
    document.body.appendChild(link)
    link.click()
    document.body.removeChild(link)
};
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Rohit Agrohia
  • 368
  • 3
  • 7
0

The file-saver package helps us to save files on the client-side for web applications.

  • Installation:

    npm i file-saver
    
  • Syntax:

    FileSaver.saveAs("https://codemaker2015.github.io/image", "image.jpg");
    
  • Usage:

    import { saveAs } from 'file-saver'
    
    const Main = () => {
        const downloadImage = () => {
            saveAs('image_url', 'image.jpg') // Put your image URL here.
        }
    
        return <Button onClick={downloadImage}>Download</Button>
    }
    

For more, see its npm page.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Codemaker2015
  • 12,190
  • 6
  • 97
  • 81
-1
const Download = () => {
  const [downloadURL, setDownloadURL] = useState("");

  const download = async () => {
    const result = await fetch(fetchURLHere, {
      method: "GET",
      headers: {},
    });
    const blob = await result.blob();
    const url = URL.createObjectURL(blob);
    setDownloadURL(url);
  };

  const handleDownload = async (e) => {
    try {
      await download();
      // Call this method when you've finished using an object URL to let the browser know not to keep the reference to the file any longer.
      URL.revokeObjectURL(downloadURL);
    } catch (error) {
      console.error(error);
    }
  };

  return (
    <button onClick={handleDownload} type="button" className="">
      <a href={downloadURL} download={setNameForFile}>
        Download Image
      </a>
    </button>
  );
};
Yilmaz
  • 35,338
  • 10
  • 157
  • 202