一、简介
之前我分享过《前端实现图片下载的方法》,但那只是针对图片下载的方法。本博客分享的是对于文件的下载方法,包括图片文件和非图片文件的下载,例如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: 要下载文件的urlfileName: 指定下载后文件的名称
*/
const downloadFile = async (url: string, fileName: string) => { // 创建XMLHttpRequest对象const http = new XMLHttpRequest();// 设置请求方式和请求地址http.open("GET", url);// 设置响应数据类型为blobhttp.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();
}