简体   繁体   中英

Downloading a file from a Node.JS API REST (express) with React.JS (Axios Get)

I have a React JS application that as a Backend has an API REST made with Node JS.

Currently, my objective is to be able to download files that are on the server. The correct behavior should be that the user, after clicking on "Download file", should receive the file (Download with browser).

On the server-side , I have something like this (obviously, I'm gonna simplify it by removing JWT middleware, DB queries, etc..):

 const express = require('express'); const router = express.Router(); const bodyParser = require("body-parser"); const cors = require("cors"); const app = express(); app.use(cors({ origin: "http://localhost:3000" })); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: true })); router.get('/download', (req, res, next) => { res.download("\\\\folder\\subfolder\\myfile.txt"); }); app.use('/api', router); const PORT = 3001; app.listen(PORT, function() { console.log("Server is running on port "+PORT); });

Then, as I have said, I have a React JS application working as a Frontend :

 apihelperdownload () { return axios.get(API_URL + "download").then(function (response) { return response; }) }............. function downloadFile() { apihelperdownload().then( (res) => { // Should I do something here with response? }, (error) => { } ) } <button className="download" onClick={() => downloadFile()}> Download File </button>

I have two files on my server, one TXT and one JPG. Both have the correct path (I'm not getting any "file/path not found" error) and I am receiving a "200 status OK" in both cases... But I can't download the files.

Also:

  • In the JPG case, in Network Tab, on preview sub-Tab I can see the image (so the browser is receiving the image).

And the response looks like this:

在此处输入图像描述

(ignore the params and the different url, it's just that here is not simplified)

- In the TXT case, in Network Tab, on preview sub-Tab I can just see a white page.

And the response looks like this:

在此处输入图像描述

As you can see, in this second case (.txt file), the data is "empty" ( "" )
Data is the correct text.. I didn't save the txt file.. So it was empty..



I have checked several related questions like this Download a file from NodeJS Server using Express

But unfortunately, I haven't found how to solve my issue.

1) What am I doing wrong on the server-side?

2) What I have to do with the response on client-side?

Thanks

I have found how to solve it without third-party libraries and in quite an "easy way".

First of all, I have changed the request to POST (since I just made GET because I thought it was the only way).

After that, on the Axios request, we have to indicate the responseType as blob:

 function apihelperdownload () { return axios.post(API_URL + "download",{ key: 'value', headers: authHeader(), responseType: 'blob' }).then(function (response) { return response; }) }

Then, when we receive the response, we have to create an URL object as a Blob and a link element to download it.

 function downloadFile(filename) { apihelperdownload().then( (res) => { const url = window.URL.createObjectURL(new Blob([res.data])); const link = document.createElement('a'); link.href = url; if (typeof window.navigator.msSaveBlob === 'function') { window.navigator.msSaveBlob( res.data, filename ); } else { link.setAttribute('download', filename); document.body.appendChild(link); link.click(); } }, (error) => { alert("Something went wrong"); } ) }

With this, we can download almost any kind of file very easily.

You can use js-file-download module.

const FileDownload = require('js-file-download');

Axios.get(API_URL + "download")
   .then((response) => {
        FileDownload(response.data, 'file.txt');
    });

Check this response for more: https://stackoverflow.com/a/41940307/6512445

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM