5

I don't know why it's happening, but it's really annoying. I expected the file to be downloaded according to the express docs. I have the next code:

  //in react (App.js)
  download = () => {
    const { images, target } = this.state;
    const filename = images.find(img => img.id === target).filename;
    fetch('http://localhost:3001/download', {
      method: 'post',
      headers: {'Content-Type': 'application/json'},
      body: JSON.stringify({filename})
    })
  }
  //in express (server.js)
  app.post('/download', (req, res) => {
    var file = '../public/images/' + req.body.filename;
    res.download(file, req.body.filename);
  });

The folder structure:

  -server
    |-server.js
  -public
    |-images
      |-a.jpg
      |-b.jpg
  -src
    |-App.js

Nothing's happening, errors not shown. Any ideas?

zero298
  • 25,467
  • 10
  • 75
  • 100
Gergő Horváth
  • 3,195
  • 4
  • 28
  • 64
  • You can find better solution [here](https://stackoverflow.com/questions/50694881/how-to-download-file-in-react-js) – MD SHAYON Oct 26 '21 at 08:45

3 Answers3

2

I think the issue you have is that you're using an HTTP POST instead of HTTP GET

Rob Brander
  • 3,702
  • 1
  • 20
  • 33
  • With get if i build a query like `download/:filename` in the server to get the filename and use `req.params.filename` instead of `req.body.filename` (because with get i can't set body), and set the request with `fetch('http://localhost:3001/download'/ + "filename"`, i get 404 error. – Gergő Horváth Sep 18 '18 at 17:38
  • how about using a query string? `fetch('http://localhost:3001/download?filename=something.dat')` – Rob Brander Sep 18 '18 at 17:45
  • try using an absolute path instead of a relative path, e.g. `path.join(__dirname, '../public/images/' + req.param.filename)` – Rob Brander Sep 18 '18 at 21:03
2

It was a challenge, but this worked for me.

    const express = require('express');
    const path = require('path');
    const port = process.env.PORT || process.argv[2] || 8080;
    const app = express();
 
    app.get('/', (req, res)=>{
      res.send('<a href="/download">Download</a>');
    });
 
    app.get('/download', (req, res)=>{
      res.download(path.join(__dirname, 'views/files.pug'), (err)=>{
        console.log(err);
      });
      console.log('Your file has been downloaded!')
    });
 
    app.listen(port, ()=>{
      console.log('res is up on port: ' + port);
    });

Just replace the file names with yours.

xgqfrms
  • 10,077
  • 1
  • 69
  • 68
1

The download method sets the Content-Disposition header which tells the browser to download it instead of navigating to it … if it were navigating to it in the first place.

You are making the request using Ajax, so the browser isn't navigating to it. The response is passed to your JS and it is the responsibility of your JS to deal with it.

You can take two approaches to this:

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335