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

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

【问题讨论】:

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

标签: javascript reactjs download


【解决方案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】:

      下载文件


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

      1. npm install --save react-download-link
      2. import DownloadLink from "react-download-link";
      3. React 客户端缓存数据的下载链接
        <DownloadLink 
            label="Download" 
            filename="fileName.txt"
            exportFile={() => "Client side cache data here…"}
        />
        
      4. 带有 Promises 的客户端缓存数据的下载链接
        <DownloadLink
            label="Download with Promise"
            filename="fileName.txt"
            exportFile={() => Promise.resolve("cached data here …")}
        />
        
      5. 使用 Promises 函数从 URL 下载数据链接以从 URL 获取数据
         getDataFromURL = (url) => new Promise((resolve, reject) => {
            setTimeout(() => {
                fetch(url)
                    .then(response => response.text())
                    .then(data => {
                        resolve(data)
                    });
            });
        }, 2000);
        
      6. 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 URLusing a CORS proxy 的解决方案。

        更新January 31st, 2021 开始,托管在 Heroku 服务器上的 cors-anywhere 演示仅允许有限地用于测试目的,不能用于生产应用程序。您必须通过cors-anywherecors-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 中的位置.

              步骤

              三个步骤:

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

              来源

              附录

              【讨论】:

              • 这是一个很酷的库。不幸的是,它仍然在新选项卡中打开了 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 文件,文件下载,但从未正确解压缩。有人可能知道它的原因吗?顺便说一句,我找到了解决方法:stackoverflow.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

                  【讨论】:

                  • 锚标签在同一浏览器选项卡中打开图像(图像预览),然后我们需要手动保存图像。我正在尝试在按钮单击时实现自动下载,而无需打开文件预览
                  • 更多详情请参考:stackoverflow.com/questions/2408146/…
                  • download 遵守同源策略仅供参考
                  • 2021 年更新:95% 的浏览器支持 download 属性:caniuse.com/download 所以...?‍♂️
                  猜你喜欢
                  • 2021-05-05
                  • 1970-01-01
                  • 2020-12-29
                  • 2021-05-17
                  • 1970-01-01
                  • 2015-09-21
                  • 2021-08-25
                  • 1970-01-01
                  相关资源
                  最近更新 更多