一、简介
之前我分享过《前端实现图片下载的方法》,但那只是针对图片下载的方法。本博客分享的是对于文件的下载方法,包括图片文件和非图片文件的下载,例如png
、doc
、pdf
、ppt
等等。
当然,还是那个大前提:在任何方案下,前端都无法绕过跨域的限制,所以如果存在跨域,那需要文件所在的服务器对当前域名开放权限,即服务器在其响应中包含适当的 CORS 头部允许跨域请求,否则是无法下载的。
二、具体方案
1、a标签跳转下载
该方式是最常用,也是最简单的方案,只需在文件资源服务器端进行配置之后,前端通过<a>
标签新开页面跳转对应链接,即可实现文件的下载。
该方案缺点是某些情况下无法指定文件下载到本地时的名称,本地文件的名称取决于文件资源服务器的文件名称。其次是如果下载文件是图片文件,则只能下载同源URL或blob:
、data:
协议的文件,对于非同源的图片只能实现查看。
<a href="https://****fileUrl" target="_blank" >下载文件</a>
2、ajax请求+a标签
该方案是通过ajax
请求,获取到blob
类型的文件数据流,然后再将文件数据流转换成URL
对象,最终再通过<a>
标签实现下载。下载时可以自定义指定文件下载到本地时的名称。而且获取blob
类型的数据,只需要前端配置ajax
请求的responseType
属性即可。
但该方案缺点是:需要将整个文件内容加载到内存中,然后再触发下载,如果下载文件过大,可能导致浏览器崩溃或者长时间无响应。
具体代码:
/*
url: 要下载文件的url
fileName: 指定下载后文件的名称
*/
const downloadFile = async (url: string, fileName: string) => {
// 创建XMLHttpRequest对象
const http = new XMLHttpRequest();
// 设置请求方式和请求地址
http.open("GET", url);
// 设置响应数据类型为blob
http.responseType = "blob";
// 监听绑定请求完成事件
http.onload = function() {
// 判断请求是否成功
if (http.status === 200) {
// 获取响应数据
const blob = http.response;
// 将blob数据 转为 URL 对象
let downloadUrl = URL.createObjectURL(blob);
// 创建一个临时的 a 标签用于触发下载
let a = document.createElement('a');
// 将url对象赋值给 a 标签的 href 属性
a.href = downloadUrl;
// 指定下载文件的名称 如果没有指定,则默认使用url中的最后一部分作为文件名
a.download = fileName || url.split('/').pop() as string;
// 将a标签添加到dom中
document.body.appendChild(a);
// 触发a标签的点击事件 开始下载文件
a.click();
// 清理:撤销创建的 URL 对象
URL.revokeObjectURL(downloadUrl);
// 并移除添加的 a 标签
document.body.removeChild(a);
}
}
// 监听绑定请求失败事件
http.onerror = function() {
console.log('下载失败,请重试或联系客服人员~');
}
// 发送请求
http.send();
}