Patrick.H
Patrick.H

Reputation: 575

ReactJS download file from Express Server

I'm trying to make my user able to download a file from our backend server. I've tried the solution from this question as well as the backend from this.

Sadly none of them worked. The download itself works through postman, but not in react.

Additional info: The Backend is running on the same machine but on port 3001 while the frontend is running on port 3000 I'm not sure if that helps, but the react frontend is connected to the backend via proxy in the package.json

"proxy": "http://localhost:3001",

The client side currently looks like this:

    const download = require("downloadjs");

    const handleDownload = async () => {
      const res = await fetch("http://localhost:3001/download");
      const blob = await res.blob();
      download(blob, "test.pdf");
    }


    function App() {
      return (
        <div className="App">
          <header className="App-header">
            <button onClick={() => handleDownload().finally(() =>                 console.log("Passed through the whole handleDownload Request"))}>                </button>
          </header>
        </div>
      );
    }

while on the backend side I'm using this code as from the previous questions asked here on stackoverflow.

    app.get('/getdoc', function (req, res) {
        res.download(path.join(__dirname, 'files/test.pdf'), function (err) {
            console.log(err);
        });
    });

This is the Code working through Postman, but it won't trigger a download in React.

The Error occurring in react looks like this:

    App.js:8 GET http://localhost:3001/download/test.pdf    net::ERR_CONNECTION_REFUSED

    Uncaught (in promise) TypeError: Failed to fetch

So it seems the handling on frontend seems to be the problem, as it is not triggering the Save Dialog from the browser (Chrome).

Upvotes: 3

Views: 15332

Answers (2)

Queens Coder
Queens Coder

Reputation: 464

Your request to postman will work because I assume you are hitting the correct endpoint which is '/getdoc' which will let you download the pdf via postman.

However, your fetch request does not seem to match the API endpoint that serves the pdf document. That is why your React Component will give you the error on download.


const handleDownload = async () => {
   const res = await fetch("http://localhost:3001/download");
   const blob = await res.blob();
   download(blob, "test.pdf");
  }

//the fetch call for "http://localhost:3001/download"  will not hit '/getdoc'

app.get('/getdoc', function (req, res) {
        res.download(path.join(__dirname, 'files/test.pdf'), function (err) {
            console.log(err);
        });
    });

Here is how I implemented the pdf download.

//resume route... this route is hit when you make a GET request to /api/resume
const router = require('express').Router();
module.exports = router;

//when route is hit the resume is downloaded
//aka /api/resume
router.get('/', (req, res, next) => {
  try {
    const file = `${__dirname}/resume/resume.pdf`;
    res.download(file);
    console.log('here');
  } catch (err) {
    console.log(err);
  }
});
//react component
import React from 'react';
import download from 'downloadjs';

const Resume = () => {
  return (
    <div>
      <button
        type="button"
        onClick={async () => {
          const res = await fetch('/api/resume');
          const blob = await res.blob();
          download(blob, 'test.pdf');
        }}
      >
        Download
      </button>
    </div>
  );
};

Upvotes: 8

mattemyo
mattemyo

Reputation: 99

Try this:

const handleDownload = () => {
var reqObj = new XMLHttpRequest();
reqObj.open('GET','http://localhost:3001/download',true);     // 'getpdf' is the URI to recongize your request at the server
reqObj.send();

reqObj.onreadystatechange = function() {
    var resObj = this;
    if(resObj.readyState == resObj.DONE) {
        if (resObj.status != 200) {
            console.log(200);
        } else if (resObj.status == 200){
            var resTxt = reqObj.responseText;
            window.location.assign(resTxt);    // Opens the pdf download prompt
        }
    }
}

Upvotes: 0

Related Questions