在web项目中实现一个当前页下载xlsx等文件功能
全栈老韩
全栈工程师,擅长iOS App开发、前端(vue、react、nuxt、小程序&Taro)开发、Flutter、React Native、后端(midwayjs、golang、express、koa)开发、docker容器、seo优化等。
一、背景
在网页上点击某一个按钮,实现下载文件的操作。
二、常见方案
2.1 服务端给一个文件对应的uri
在前端网页上,使用a标签,标签href中设置下载文件对应的链接,一般就可以实现跳转下载文件。
example:
html
<a href="https://www.xxx.com/xxx.txt">下载</a>
情况往往没有设定文件下载权限,文件链接暴露的话,任何人都可以下载这个文件。
如果是同源的情况下(网页域名和下载域名符合同源策略),那么一般还比较容易做到鉴权,但实际开发过程中,web服务器和文件服务器是做分离的,所以这种情况是难以做到鉴权的。
2.2 使用接口获取文件流方式
这种方式需要服务端做好配置,读取文件后,并且要设置response header,前端请求文件流接口,接口统一封装了对应的token信息。
2.2.1 前端请求接口
不管是vue还是react项目,哪怕使用fetch,都是很容易在request header中加入对应的authorization信息,服务端就可以使用jwt来判断是否允许下载。
对于使用axios框架来说,更是非常简单的,这里不赘述,咱们重点放在请求后的处理上。
2.2.2 后端读取文件
这种方式需要服务端做好配置,不仅返回的是文件流,而且要设置对应的response header,咱们拿一个xlsx文件类型举例:

如图所示,服务端要设置一下返回的内容类型:
content-disposition:
attachment; filename=data_20241014040517.xlsx
content-type:
application/octet-stream
2.2.3 前端读取文件流为blob
直接上代码。主要逻辑就是使用fetch的response.blob方法将流转成blob对象,然后新建一个a标签,模拟点击,实现在当前页面就可以下载文件下来。
js
const userStore = useUserStoreHook();
const token = userStore.accessToken
fetch(`${import.meta.env.Fascin8_APP_BASE_URL}/admin/billing/export?` + downloadParam({...param}).substring(1), {
method: 'GET',
headers: {
'Authorization': token,
},
})
.then(response => {
console.log("请求结果是:", response)
if (!response.ok) {
throw new Error('Network response was not ok');
}
// 从header的Content-Disposition中获取文件名
const contentDisposition = response.headers.get('Content-Disposition');
let filename = ''
if (contentDisposition && contentDisposition.indexOf('attachment') !== -1) {
const filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
const matches = filenameRegex.exec(contentDisposition);
if (matches != null && matches[1]) {
filename = matches[1].replace(/['"]/g, ''); // Remove extra quotes
}
} else {
// 自定义一个文件名
filename = 'data_' + moment().format("YYYYMMDDHHmmss") + '.xlsx'
}
return response.blob().then(blob => ({ blob, filename }));
})
.then(({ blob, filename }) => {
// 创建a标签,并且触发下载
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
})
发布于2024-10-14 09:58:19
浏览量195·
暂无评论,快来发表第一条评论吧