ReactJS从Express服务器下载文件。

3
我正在尝试让用户从我们的后端服务器下载文件。我已经尝试了来自这个问题的解决方案以及来自这里的后端,但很遗憾它们都没能成功。通过postman下载本身是有效的,但在react中无法实现。
附加信息:后端和前端在同一台机器上运行,但端口号分别为3001和3000。我不确定这是否有所帮助,但是在package.json中,react前端通过代理连接到后端。
"proxy": "http://localhost:3001",

客户端目前看起来像这样:
    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>
      );
    }

在后端方面,我正在使用此代码,这是从此前在stackoverflow上提出的问题中得到的。

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

这是在Postman上运行的代码,但它在React中无法触发下载。

在React中出现的错误如下:

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

    Uncaught (in promise) TypeError: Failed to fetch

看起来前端处理似乎是问题所在,因为它无法从浏览器(Chrome)触发保存对话框。

2个回答

8
你的请求将在postman上工作,因为我假定你正在访问正确的端点“/getdoc”,这将允许你通过postman下载pdf文件。
然而,你的fetch请求似乎与提供pdf文档的API端点不匹配。这就是为什么你的React组件会在下载时给出错误提示。

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

这是我实现 PDF 下载的方式。

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

1
能否在不使用“下载”模块的情况下下载文件? - Sanket
2
当然,有很多可以使用的软件包,或者您可以不使用软件包。下载文件最简单的方法是创建一个带有文件URL的链接,并将其包含在您的HTML / React / 前端中。 - Queens Coder
谢谢你的回答!如果你正在使用axios,你可以通过在选项中添加responseType=blob来做同样的事情。 - undefined

0

试试这个:

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

我仍然收到错误信息: App.js:7 GET http://localhost:3001/download net::ERR_CONNECTION_REFUSED这是reqObj.open('GET',...)的那一行代码。状态码为0。 - Patrick.H
你可以尝试在浏览器的 URL 地址栏直接访问 http://localhost:3001/download 吗? - mattemyo
它以相同的错误响应,这是奇怪的事情... 在 Postman 中,我可以毫无问题地下载文件。 - Patrick.H
或许你需要指定fetch的头部。 - mattemyo
是的,我有并且仍然收到“ERR_CONNECTION_REFUSED”消息。我不知道要设置哪些标头,因为这是一个简单的get请求。 - Patrick.H

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接