这是对早期答案的完全重写,如果有人需要这个答案,很抱歉,但这个版本更优秀。我正在使用一个用express-generator 创建的项目并在三个文件中工作:
- 路线/index.js
- 视图/index.ejs
- 公共/javascripts/main.js
索引.ejs
从具有以下内容的锚标记开始download
属性,使用您想要的任何文件名,以及一个空href
属性。我们将填写href
在 main.js 文件中,其中包含代表 Excel 文件的 ObjectURL:
<body>
<a id="downloadExcelLink" download="excelFile.xlsx" href="#">Download Excel File</a>
<script type="text/javascript" src="/javascripts/main.js"></script>
</body>
公共/javascripts/main.js
选择锚元素,然后制作一个fetch()
请求路线/downloadExcel
。将响应转换为Blob
,然后创建一个ObjectURL
由此Blob
。然后您可以设置href
锚标记的属性为此ObjectURL
:
const downloadExcelLink = document.getElementById('downloadExcelLink');
(async () => {
const downloadExcelResponse = await fetch('/downloadExcel');
const downloadExcelBlob = await downloadExcelResponse.blob();
const downloadExcelObjectURL = URL.createObjectURL(downloadExcelBlob);
downloadExcelLink.href = downloadExcelObjectURL;
})();
路线/index.js
在索引路由器中,您只需调用res.sendFile()
函数并将其传递给服务器上 Excel 文件的路径。
router.get('/downloadExcel', (req, res, next) => {
const excelFilePath = path.join(__dirname, '../tmp/excel.xlsx');
res.sendFile(excelFilePath, (err) => {
if (err) console.log(err);
});
});
就是这样!你可以找到一个 git 仓库here https://github.com/Dayun123/stack-overflow--download-excel项目的。如果您无法让此代码按原样在您的项目中工作,请克隆并亲自尝试一下。
怎么运行的
当页面加载时,会向我们的服务器发出 4 个请求,正如我们在控制台输出中看到的那样:
GET / 200 2.293 ms - 302
GET /stylesheets/style.css 200 1.123 ms - 111
GET /javascripts/main.js 200 1.024 ms - 345
GET /downloadExcel 200 2.395 ms - 4679
前三个请求针对的是index.ejs (/)、CSS 样式表和我们的main.js 文件。第四个请求是通过我们的电话发送的fetch('/downloadExcel')
在 main.js 文件中:
const downloadExcelResponse = await fetch('/downloadExcel');
我在routes/index.js中有一个路由处理程序设置,该路由使用res.sendFile()
从我们的文件系统发送一个文件作为响应:
router.get('/downloadExcel', (req, res, next) => {
const excelFilePath = path.join(__dirname, '../tmp/excel.xlsx');
res.sendFile(excelFilePath, (err) => {
if (err) console.log(err);
});
});
excelFilePath
需要是您系统上文件的路径。在我的系统上,以下是路由器文件和 Excel 文件的布局:
/
/routes/index.js
/tmp/excel.xlsx
从我们的 Express 服务器发送的响应存储在downloadExcelResponse
作为调用的返回值fetch()
在 main.js 文件中:
const downloadExcelResponse = await fetch('/downloadExcel');
downloadExcelResponse
is a Response
对象,为了我们的目的,我们想把它变成一个Blob
对象使用Response.blob()
method:
const downloadExcelBlob = await downloadExcelResponse.blob();
现在我们有了Blob
,我们可以调用URL.convertObjectURL()
转动这个Blob
变成我们可以用作的东西href
我们的下载链接:
const downloadExcelObjectURL = URL.createObjectURL(downloadExcelBlob);
此时,我们在浏览器中就有了代表 Excel 文件的 URL,我们可以将href
通过将其添加到我们之前选择的 DOM 元素来添加到此 URLhref
财产:
当页面加载时,我们用这一行选择了锚元素:
<a id="downloadExcelLink" download="excelFile.xlsx" href="#">Download Excel File</a>
所以我们将 URL 添加到href
在这里,在使fetch
要求:
downloadExcelLink.href = downloadExcelObjectURL;
您可以在浏览器中查看该元素并看到href
页面加载时属性已更改:
请注意,在我的计算机上,锚标记现在是:
<a id="downloadExcelLink" download="excelFile.xlsx" href="blob:http://localhost:3000/aa48374e-ebef-461a-96f5-d94dd6d2c383">Download Excel File</a>
自从download
属性存在于链接上,当单击链接时,浏览器将下载任何内容href
指向,在我们的例子中是 URLBlob
代表 Excel 文档。
我从以下来源获取信息:
- JavaScript.info - Blob 作为 URL https://javascript.info/blob#blob-as-url
- Javascript.info - 获取 https://javascript.info/fetch
这是下载过程在我的机器上的样子的 gif: