reactjs如何下载文件

Posted

技术标签:

【中文标题】reactjs如何下载文件【英文标题】:how to download file in react js 【发布时间】:2018-11-14 15:11:41 【问题描述】:

我从 api 收到文件 url 作为响应。当用户单击下载按钮时,应下载文件,而无需在新选项卡中打开文件预览。如何在 React js 中实现这一点?

【问题讨论】:

从前端触发浏览器下载并不是一种可靠的方法。您应该创建在调用时将提供正确响应标头的端点,从而触发浏览器下载。前端代码只能做这么多。例如,“下载”属性可能只是在新选项卡中打开文件,具体取决于浏览器。 根据我的理解,你是说rest api可以通过正确的响应头来实现,对吗? 是的。我不知道如何在评论中附加链接,所以我发布了一个答案。 【参考方案1】:

从前端触发浏览器下载不可靠。

你应该做的是,在服务器上创建一个端点,当被调用时,它会以正确的响应头响应,从而触发浏览器下载。

前端代码只能做这么多。例如,“下载”属性可能只是在新选项卡中打开文件,具体取决于浏览器和文件类型。

您需要查看的响应标头是Content-TypeContent-Disposition。您应该查看answer 以获取有关这些标题的更详细说明。

【讨论】:

你应该做的是,创建一个端点,当被调用时,它将提供正确的响应头,从而触发浏览器下载......这些头是什么以及具体的头如何触发浏览器下载?谢谢 您好,抱歉回复晚了。有问题的标题是Content-TypeContent-Disposition【参考方案2】:

出色而快速的解决方案:

window.open('https://myapi.com/download/file-name')

【讨论】:

【参考方案3】:
fetchFile()
  axios(
        url: `/someurl/thefiles/$this.props.file.id`,
        method: "GET",
        headers: headers,
        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",
            `$this.props.file.name.$this.props.file.mime`
        );
        document.body.appendChild(link);
        link.click();

        // Clean up and remove the link
        link.parentNode.removeChild(link);
    );

render()
  return( <button onClick=this.fetchFile> Download file </button>)

【讨论】:

请注意,如果页面未在您的应用中重新加载,则传递给“URL.createObjectURL”的 blob 将保留在内存中,直到您调用 URL.revokeObjectUrl。对于长时间运行的应用,这可能会导致内存浪费和性能问题。【参考方案4】:

import resume from '../assets/data/resume.pdf';

<a href=resume download="YourName resume.pdf"> Download CV </a>

【讨论】:

我能够以同样的方式添加一个 epub 文件【参考方案5】:

解决我的下载链接问题的包是:

npm install --save react-download-link

像这样使用它:

fileDownload(axiosResponse.data, 'filename.csv');

您可以创建例如在后端有这样的 C# Web API 端点:

[HttpGet("GenerateSitemap")]
public async Task<IActionResult> GenerateSitemap()

    var sitemapString = "[place-xml-sitemap-string-here]";
    var serializedObj = JsonConvert.SerializeObject(obj);
    var bytesObj = Encoding.UTF8.GetBytes(serializedObj);

    return File(sitemapString.SerializeToByteArray(), "application/octet-stream");

【讨论】:

【参考方案6】:

下载文件


对于下载,您可以使用上面解释的多种方式,此外,我还将针对这种情况提供我的策略。

    npm install --save react-download-link import DownloadLink from "react-download-link"; React 客户端缓存数据的下载链接
    <DownloadLink 
        label="Download" 
        filename="fileName.txt"
        exportFile=() => "Client side cache data here…"
    />
    
    带有 Promises 的客户端缓存数据的下载链接
    <DownloadLink
        label="Download with Promise"
        filename="fileName.txt"
        exportFile=() => Promise.resolve("cached data here …")
    />
    
    使用 Promises 函数从 URL 下载数据链接以从 URL 获取数据
     getDataFromURL = (url) => new Promise((resolve, reject) => 
        setTimeout(() => 
            fetch(url)
                .then(response => response.text())
                .then(data => 
                    resolve(data)
                );
        );
    , 2000);
    
    DownloadLink 组件调用 Fetch 函数
    <DownloadLink
          label=”Download”
          filename=”filename.txt”
          exportFile=() => Promise.resolve(this. getDataFromURL (url))
    />
    

编码愉快! ;)

【讨论】:

【参考方案7】:

tldr; 从 url 获取文件,将其存储为本地 Blob,将链接元素注入 DOM,然后单击以下载 Blob

我有一个 PDF 文件存储在 Cloudfront URL 后面的 S3 中。我希望用户能够单击按钮并立即启动下载,而无需打开带有 PDF 预览的新标签。通常,如果文件托管在与用户当前所在站点具有不同域的 URL 上,出于用户安全原因,许多浏览器会阻止立即下载。如果您使用此解决方案,请不要启动文件下载,除非用户单击按钮有意下载。

为了解决这个问题,我需要从绕过任何 CORS 策略的 URL 中获取文件,以保存一个本地 Blob,然后该 Blob 将成为下载文件的源。在下面的代码中,请确保您交换了自己的 fileURLContent-TypeFileName

fetch('https://cors-anywhere.herokuapp.com/' + fileURL, 
    method: 'GET',
    headers: 
      'Content-Type': 'application/pdf',
    ,
  )
  .then((response) => response.blob())
  .then((blob) => 
    // Create blob link to download
    const url = window.URL.createObjectURL(
      new Blob([blob]),
    );
    const link = document.createElement('a');
    link.href = url;
    link.setAttribute(
      'download',
      `FileName.pdf`,
    );

    // Append to html link element page
    document.body.appendChild(link);

    // Start download
    link.click();

    // Clean up and remove the link
    link.parentNode.removeChild(link);
  );

此解决方案参考getting a blob from a URL 和using a CORS proxy 的解决方案。

更新 从 January 31st, 2021 开始,托管在 Heroku 服务器上的 cors-anywhere 演示仅允许有限地用于测试目的,不能用于生产应用程序。您必须通过cors-anywhere 或cors-server 来托管您自己的 cors-anywhere 服务器。

【讨论】:

【参考方案8】:

我们可以使用 react-download-link 组件将内容下载为文件。

<DownloadLink
label="Download"
filename="fileName.txt"
exportFile=() => "Client side cache data here…"/>

https://frugalisminds.com/how-to-download-file-in-react-js-react-download-link/

【讨论】:

【参考方案9】:

解决方案(适用于 React JS、Next JS)

您可以使用 js-file-download,这是我的示例:

import axios from 'axios'
import fileDownload from 'js-file-download'
 
...

handleDownload = (url, filename) => 
  axios.get(url, 
    responseType: 'blob',
  )
  .then((res) => 
    fileDownload(res.data, filename)
  )

 
...

<button onClick=() => this.handleDownload('https://your-website.com/your-image.jpg', 'test-download.jpg')
>Download Image</button>

此插件可以下载excel等文件类型。

【讨论】:

这很好用,要求另存为,这是我正在寻找的 下载后无法打开文件,文件错误:“文件(nameFile)无法打开。它可能已损坏或使用了预览无法识别的文件格式。”我错过了什么吗? 它对我有用。感谢您提供此解决方案。【参考方案10】:

您可以使用FileSaver.js 来实现这个目标:

const saveFile = () => 
fileSaver.saveAs(
  process.env.REACT_APP_CLIENT_URL + "/resources/cv.pdf",
  "MyCV.pdf"
);

;

<button className="cv" onClick=saveFile>
    Download File
</button>

【讨论】:

使用fileSaver时会在新标签页打开pdf @DivyeshKanzariya 你怎么能解决这个问题?【参考方案11】:

这就是我在 React 中的做法:

import MyPDF from '../path/to/file.pdf';
<a href=myPDF download="My_File.pdf"> Download Here </a>

使用download="name_of_file_you_want.pdf" 覆盖默认文件名很重要,否则下载时文件会附上一个哈希号。

【讨论】:

【参考方案12】:

我有完全相同的问题,这是我现在使用的解决方案: (注意,这对我来说似乎很理想,因为它使文件与从 Amazon S3 加载的 SinglePageApplication React 应用程序密切相关。所以,这就像存储在 S3 和应用程序中,相对而言,它知道它在 S3 中的位置.

步骤

三个步骤:

    在项目中使用文件保护程序:npmjs/package/file-saver(npm install file-saver 什么的) 将文件放入您的项目中您说它在 components 文件夹中。好吧,如果你有 web-pack,它可能会尝试缩小它。(有人请指出 webpack 会对 components 文件夹中的资产文件做什么),所以我认为这不是你想要的.因此,我建议将资产放入public 文件夹中,使用resourceasset 名称。 Webpack 不会触及 public 文件夹和 index.html 并且您的资源会按原样复制到生产构建中,您可以在下一步中引用它们。 参考你项目中的文件 示例代码:
    import FileSaver from 'file-saver';
    FileSaver.saveAs(
        process.env.PUBLIC_URL + "/resource/file.anyType",
        "fileNameYouWishCustomerToDownLoadAs.anyType");
    

来源

Create-React-App.dev | Using the public folder Github | File saver documentation

附录

我还尝试了react-routerreact-router-docs/Link 的Link 组件。 zip 文件将下载,并以某种方式正确解压缩。一般来说,链接是蓝色的,要继承父配色方案,只需添加一个类似的道具:style=color: inherit 或简单地分配你的 CSS 库的一个类,如 button button-primary 或其他东西,如果你是 Bootstrappin' 与它密切相关的其他圣人问题: download file in react how to download file in react js button to download a file in reactJS download sample file in public folder (react)

【讨论】:

这是一个很酷的库。不幸的是,它仍然在新选项卡中打开了 PDF。不过,它使动态打开文件成为一个非常干净的过程。【参考方案13】:

a 标记与target="_blank" 一起使用时,React 会出现安全问题。

我设法让它像这样工作:

<a href=uploadedFileLink target="_blank" rel="noopener noreferrer" download>
   <Button>
      <i className="fas fa-download"/>
      Download File
   </Button>
</a>

【讨论】:

【参考方案14】:

您可以定义一个组件并在任何地方使用它。

import React from 'react';
import PropTypes from 'prop-types';


export const DownloadLink = ( to, children, ...rest ) => 

  return (
    <a
      ...rest
      href=to
      download
    >
      children
    </a>
  );
;


DownloadLink.propTypes = 
  to: PropTypes.string,
  children: PropTypes.any,
;

export default DownloadLink;

【讨论】:

【参考方案15】:

如果您使用的是 React Router,请使用:

<Link to="/files/myfile.pdf" target="_blank" download>Download</Link>

/files/myfile.pdf 在您的public 文件夹中的位置。

【讨论】:

我尝试使用 zip 文件,文件下载,但从未正确解压缩。有人可能知道它的原因吗?顺便说一句,我找到了解决方法:***.com/a/62855917/7622204【参考方案16】:

浏览器足够智能,可以检测链接并在单击锚标记时直接下载链接,而无需使用下载属性。

从 api 获取文件链接后,只需通过创建锚标记使用纯 javascript 并在动态单击后立即将其删除。

const link = document.createElement('a');
link.href = `your_link.pdf`;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);

【讨论】:

除了浏览器会打开一个PDF,我想下载它。未开放。 它也适用于 react 和 node/HAPI。我在下面添加了 link.href = your_link.pdf;链接下载=yourFileName;非常感谢。【参考方案17】:

这与 React 无关。但是,您可以使用锚点 &lt;a&gt; 元素上的 download 属性来告诉浏览器下载文件。

<a href='/somefile.txt' download>Click to download</a>

并非所有浏览器都支持此功能:https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a

【讨论】:

锚标签在同一浏览器选项卡中打开图像(图像预览),然后我们需要手动保存图像。我正在尝试在按钮单击时实现自动下载,而无需打开文件预览 更多详情请参考:***.com/questions/2408146/… download 遵守同源策略仅供参考 2021 年更新:95% 的浏览器支持 download 属性:caniuse.com/download 所以...?‍♂️

以上是关于reactjs如何下载文件的主要内容,如果未能解决你的问题,请参考以下文章

将 ReactJS 对象下载为文件

从服务器 Laravel 和 reactjs 下载文件

ReactJS:单击按钮下载 CSV 文件

无法使用reactjs下载文件

Reactjs 记录器-js 下载

如何重置 ReactJS 文件输入