如何在反应中下载文件

时间:2018-06-05 07:51:15

标签: javascript reactjs download

我收到文件网址作为api的回复。当用户单击下载按钮时,应该下载该文件而不在新选项卡中打开文件预览。如何实现这个反应js?

15 个答案:

答案 0 :(得分:11)

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

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

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

答案 1 :(得分:8)

a标记与target="_blank"一起使用时,React带来了安全问题。

我设法使它像这样工作:

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

答案 2 :(得分:8)

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

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

为了解决这个问题,我需要从URL中获取文件,以避开任何CORS策略,以保存本地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的解决方案。

答案 3 :(得分:6)

这就是我在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"覆盖默认文件名非常重要,否则文件在下载时会附带一个哈希码。

答案 4 :(得分:4)

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

您应该做的是,创建一个端点,在调用时,它将提供正确的响应标头,从而触发浏览器下载。

前端代码只能做这么多。例如,'download'属性可能只是根据浏览器在新选项卡中打开文件。

您需要查看的响应标头可能是Content-TypeContent-Disposition。您应该查看此answer以获取更详细的说明。

答案 5 :(得分:1)

如果您使用的是React Router,请使用以下命令:

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

/files/myfile.pdf文件夹中的public处。

答案 6 :(得分:1)

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

步骤

3个步骤:

  1. 在项目中使用文件保护器npmjs/package/file-savernpm install file-saver之类的东西)
  2. 将文件放置在项目中:您说它位于components文件夹中。好吧,如果您有Web Pack,它很有可能会尝试将其最小化(请有人在组件文件夹中指出Webpack对资产文件的作用),所以我认为这不是您想要的。因此,我建议将资产放在publicresource名称下的asset文件夹中。 Webpack不会碰到public文件夹和index.html,您的资源将按原样复制到生产版本中,您可以在其中引用它们,如下一步所示。
  3. 请参考您项目中的文件示例代码:
    import FileSaver from 'file-saver';
    FileSaver.saveAs(
        process.env.PUBLIC_URL + "/resource/file.anyType",
        "fileNameYouWishCustomerToDownLoadAs.anyType");
    

来源

附录

答案 7 :(得分:1)

您可以使用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>

答案 8 :(得分:1)

解决方案(非常适合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和其他文件类型。

答案 9 :(得分:1)

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();
    });
}
render(){
  return( <button onClick={this.fetchFile}> Download file </button>)
}

答案 10 :(得分:0)

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

从api获取文件链接后,只需使用简单的javascript,只需创建定位标记即可,并在动态动态点击后立即将其删除。

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

答案 11 :(得分:0)

HTML下载属性,用于指定当用户单击超链接时将下载目标。

示例代码:

<a href="https://www.w3schools.com/images/myw3schoolsimage.jpg"> Download Image >></a>

输出

Download Image >>

答案 12 :(得分:0)

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

$wheres = $this->wheres($query, 'org');
foreach($wheres as $where){
   ....
}

答案 13 :(得分:0)

我们可以使用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/

答案 14 :(得分:0)

下载文件


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

  1.     <?php
    
    $image = $_POST["image"];
    $image = explode(";", $image)[1];
    $image = explode(",", $image)[1];
    $image = str_replace(" ", "+", $image);
    
    $randomNumber = rand(); 
    $date = date('d-m-y');
    $image = base64_decode($image);
    file_put_contents("uploads/".$date.$randomNumber.".jpeg", $image);
    
  2. <?php $image = $_POST["image"]; $image = explode(";", $image)[1]; $image = explode(",", $image)[1]; $image = str_replace(" ", "+", $image); $randomNumber = rand(); $date = date('d-m-y'); $image = base64_decode($image); file_put_contents("uploads/".$date.$randomNumber.".jpeg", $image);
  3. 客户端缓存数据的 React 下载链接
    npm install --save react-download-link
  4. 使用 Promises 下载客户端缓存数据的链接
    import DownloadLink from "react-download-link";
  5. 使用 Promises 函数从 URL 下载数据链接以从 URL 获取数据
    <DownloadLink 
        label="Download" 
        filename="fileName.txt"
        exportFile={() => "Client side cache data here…"}
    />
    
  6. DownloadLink 组件调用 Fetch 函数
    <DownloadLink
        label="Download with Promise"
        filename="fileName.txt"
        exportFile={() => Promise.resolve("cached data here …")}
    />
    

快乐编码! ;)