3

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).

Patrick.H
  • 535
  • 3
  • 6
  • 21

2 Answers2

7

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>
  );
};
Queens Coder
  • 331
  • 4
  • 9
  • 1
    Is it possible to download the file without using the "download" module ? – Sanket Feb 05 '22 at 14:12
  • 2
    of course, there are a ton of packages you can use, or you could do it without one. the easiest way to download a file would be to create a link with the URL to the file and include that in your HTML/React/Frontend – Queens Coder Mar 01 '22 at 15:24
0

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
        }
    }
}
mattemyo
  • 99
  • 1
  • 4
  • I still get the Err: App.js:7 GET http://localhost:3001/download net::ERR_CONNECTION_REFUSED which is the line of: reqObj.open('GET',...); and status code = 0 – Patrick.H May 26 '19 at 13:21
  • could you try to access http://localhost:3001/download directly in the url bar of your browser? – mattemyo May 26 '19 at 13:23
  • It responds with the same error, that's the strange thing... In Postman I can download the file without any problems – Patrick.H May 26 '19 at 13:24
  • or maybe you would have to specify the headers of the fetch – mattemyo May 26 '19 at 14:30
  • yes i have and I still get the ERR_CONNECTION_REFUSED message. I wouldn't know which headers to set, since this is a simple get request – Patrick.H May 26 '19 at 14:36