使用 React 和 Axios 从 Express API 下载文件

Ben*_*Ben 3 javascript express reactjs axios

当使用带有 Express API 的 React 客户端时,React 客户端如何下载 Express API 发送的文件?

问题:

  • 如果我在浏览器栏中输入网址并按 Enter 键,则文件下载成功。
  • 但是,如果我使用 Axios 在 React 应用程序中调用相同的 url,则该文件不会下载。

快递服务器

// Route handler for /api/files/testfile
const getFile = async (req, res, next) => {

    // File
    const fileName = 'file.csv';
    const filePath = path.join(__dirname, '/../../public/', fileName);

    // File options
     const options = {
        headers: {
            'x-timestamp': Date.now(),
            'x-sent': true,
            'content-disposition': "attachment; filename=" + fileName, // gets ignored
            'content-type': "text/csv"
        }
    }

    try {
        res.download(
            filePath,
            fileName,
            options
        );
        console.log("File sent successfully!");
    }
    catch (error) {
        console.error("File could not be sent!");
        next(error);
    }
});
Run Code Online (Sandbox Code Playgroud)

反应客户端

// When the user clicks the "Download as CSV" button
handleDownloadFile = () => {
    axios
        .get(
            `/api/files/testfile`, {
                responseType: 'blob',
                headers: {
                    'Content-Type': 'text/csv',
                }
            }
        )
        .then(response => {
            console.log(response.headers); // does not include content-disposition
            console.log("File downloading successfully!");
        })
        .catch( (error) => {
            console.error("File could not be downloaded:", error);
        });
}
Run Code Online (Sandbox Code Playgroud)

我读到这可能与标题有关content-disposition。我尝试设置(请参阅上面的代码),但标头没有发送到客户端。


不需要的“解决方案”:

  • 在 React 应用程序中:创建一个新a元素,设置其href属性并通过 JavaScript 触发click。我正在寻找一个不需要这种 JS hack 的解决方案。

  • 在 React 应用程序中:使用awithtarget="_blank"代替 Axios。但是,这不适合我,因为它会绕过我的 axios 配置设置(API url、身份验证令牌等)

Atl*_*ila 6

看来你必须直接根据这个例子告诉 axios 文件在哪里:

axios({
  url: 'http://localhost:5000/static/example.pdf',
  method: 'GET',
  responseType: 'blob', // important
}).then((response) => {
  const url = window.URL.createObjectURL(new Blob([response.data]));
  const link = document.createElement('a');
  link.href = url;
  link.setAttribute('download', 'file.pdf');
  document.body.appendChild(link);
  link.click();
});
Run Code Online (Sandbox Code Playgroud)

我假设您可以简单地更改 api 上的响应,以使用文件的新 Blob 返回 blob。但它似乎需要的主要部分是 axios get 调用上的 .then 响应。这样您仍然可以使用 jwt 验证用户的状态并适当地保护您的文件。