如何在 response js 中下载文件

我从 api 接收文件 URL 作为响应。当用户点击下载按钮时,文件应该在新的选项卡中不打开文件预览就可以下载。如何在反应中实现这一点?

530141 次浏览

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

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

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

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

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

前端代码只能做这么多。例如,“ download”属性可能会根据浏览器和文件类型在新的选项卡中打开文件。

您需要查看的响应头是 Content-TypeContent-Disposition。您应该检查这个 回答以获得关于这些头的更详细的解释。

浏览器足够聪明,能够在不使用 download 属性的情况下单击锚标记时检测到链接并直接下载它。

在从 api 获得文件链接之后,只需通过创建锚标记使用普通的 javascript,并在动态地立即点击它之后删除它。

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

如果你正在使用 React 路由器,请使用以下命令:

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

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

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

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;

React 在使用 a标签和 target="_blank"时会出现安全问题。

我设法让它像这样工作:

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

我在《反应》中是这样做的:

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

使用 download="name_of_file_you_want.pdf"覆盖默认文件名很重要,否则在下载时文件将获得附加到它的散列号。

我也有同样的问题,下面是我现在使用的解决方案: (注意,这对我来说似乎很理想,因为它将文件紧密地绑定到从 Amazon S3加载的 SinglePageApplicationReact 应用程序。因此,它就像是存储在 S3上,在应用程序中,相对而言,它知道自己在 S3中的位置。

步骤

3个步骤:

  1. 在项目 : Npmjs/package/file-saver(npm install file-saver或其他)中使用文件保护程序
  2. 将文件放在您的项目 中,您说它在组件文件夹中。那么,如果你有网络包,它很有可能会试图缩小它。(有人请查明什么是 webpack 会做的组件文件夹中的资产文件) ,所以我不认为这是你想要的。因此,我建议将资产放在 public文件夹中,放在 resourceasset名称下。Webpack 不会触及 public文件夹和 index.html,您的资源将在生产构建中按原样复制,您可以在下一步中引用它们。
  3. 参考项目中的文件 示例代码:
    import FileSaver from 'file-saver';
    FileSaver.saveAs(
    process.env.PUBLIC_URL + "/resource/file.anyType",
    "fileNameYouWishCustomerToDownLoadAs.anyType");
    

来源

附录

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

Tldr; 从 URL 获取文件,将其存储为本地 Blob,将 link 元素注入 DOM,然后单击它下载 Blob

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

为了解决这个问题,我需要绕过 CORS 策略从 URL 中获取文件,以保存本地 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);
});

这个解决方案参考了 从一个 URL 获取一个斑点使用 CORS 代理的解决方案。

更新2021年1月31日开始,Heroku 服务器上托管的 cors-where 演示将只允许有限的测试用途,不能用于生产应用程序。您必须遵循 任何地方Cors-server托管您自己的 cors-where 服务器。

解决方案 (工作完美的反应 JS,下一个 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 和其他文件类型。

我们可以使用用户反应-下载-链接组件将内容作为文件下载。

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

下载文件


对于下载,你可以使用多种方法,如上所述,此外,我也将提供我的策略,这个场景。

  1. npm install --save react-download-link
  2. import DownloadLink from "react-download-link";
  3. 反应客户端缓存数据的下载链接
    <DownloadLink
    label="Download"
    filename="fileName.txt"
    exportFile={() => "Client side cache data here…"}
    />
    
  4. 客户端缓存数据的下载链接与承诺
    <DownloadLink
    label="Download with Promise"
    filename="fileName.txt"
    exportFile={() => Promise.resolve("cached data here …")}
    />
    
  5. 下载从 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))}
    />
    

编程愉快! ;)

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

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

Npm install —— save response-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");
}

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

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

最好的快速解决方案:

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

我已经试过这个 DownloadLink,它从 API 中获取数据,我可以使用 dev 工具看到这一点,但它不会触发文件下载。知道我错过了什么吗?

这就是我用过的方法:

getDataFromURL = (url) => new Promise((resolve, reject) => {
setTimeout(() => {
fetch(url)
.then(response => response.text())
.then(data => {
resolve(data)
});
});
});

很多好的答案,我认为布莱恩李的答案是好的。要挑剔的是,获取中的 Content-Type 用于当您将 发送中数据传送到服务器而没有接收到时。

对于那些还没有重新加载的持久应用程序来说,确保在使用链接之后执行 URL.revokeObjectURL (url)也很重要。如果您不再使用该链接,也应该删除该链接:))