使用 React.JS (Axios Get) 从 Node.JS API REST (express) 下载文件

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

我有一个 React JS 应用程序,作为后端有一个 API 用 Node JS 制作的 REST。

目前,我的 objective 是能够下载服务器上的文件。 正确的行为应该是用户在单击“下载文件”后应该收到文件(使用浏览器下载)。

服务器端,我有这样的东西(显然,我将通过删除 JWT 中间件、数据库查询等来简化它):

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);
});

然后,正如我所说,我有一个 React JS 应用程序作为 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>

我的服务器上有两个文件,一个TXT 和一个JPG。 两者都有正确的路径(我没有收到任何“file/path not found”错误)并且在这两种情况下我都收到“200 status OK”...但是我无法下载文件。

还有:

响应如下所示:

(忽略参数和不同的url,只是这里没有简化)

- 在 TXT 的情况下,在网络选项卡中,在预览子选项卡上我只能看到一个白页。

响应如下所示:

如您所见,在第二种情况(.txt 文件)中,数据为“空”( "" )
数据是正确的文本..我没有保存txt文件..所以它是空的..



我查了好几个相关问题都是这样Download a file from NodeJS Server using Express

但不幸的是,我还没有找到解决问题的方法。

1) 我在服务器端做错了什么?

2) 客户端的响应与我有什么关系?

谢谢

您可以使用 js-file-download 模块。

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

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

查看此回复了解更多信息:

我找到了如何在没有第三方库的情况下以相当“简单的方式”解决它。

首先,我已经将请求更改为POST(因为我认为这是唯一的方法,所以我刚刚进行了GET)。

之后,在 Axios 请求中,我们必须将 responseType 指定为 blob:

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

然后,当我们收到响应时,我们必须创建一个 URL 对象作为 Blob 和一个 link 元素来下载它。

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");
      }
  )
  
}

有了这个,我们可以非常轻松地下载几乎任何类型的文件。