赞
踩
说明:
本文档目标为给 在项目中用到下载(导出)文件功能做一个参考。 由于本文档只在PC端验证过效果,移动端没做验证,故本文档适用于PC端页面。
下载(导出):页面常用的下载模板、导出excel功能。
前端在做项目过程中,会遇到在页面下载文件需求。本文档根据项目中实际用到的几种下载文件方式做一个归纳总结。
页面下载(导出)功能采用调用接口的方式(和其他调用接口方式一样),可以实现在请求前后做处理(加反馈效果---如loading、弹窗提示等),便于处理接口响应,给出友好反馈。
本方案没有实现进度条功能,没有实现在移动端(浏览器、微信网页、小程序、app内嵌网页)中的下载导出文件功能。
代码示例:
window.location.href = '/aps/aps-web/common/comDownload?downloadType=1';
如果需要参数,就以query方式拼接到url后。如?downloadType=1&businessType=2;
请求只能是get方式。
表现形式:点击下载按钮,执行上述代码,浏览器地址栏刷新(刷新半圈箭头图标会变成x号,表示当前页正在加载),识别到后台此地址返回的数据后,页面开始进行下载(浏览器左下角出现下载进度栏,可以选在下载完成后打开文件)。
优势:代码简单,一句代码即可实现下载功能。
不足:
1、图片、pdf、doc等资源会直接加载(预览)页面(当前页面变成相应资源---相当于直接访问资源链接),当前页面会变成资源页面,严重影响用户体验。
2、无法处理成功和失败,无法给用户反馈(加loading、弹窗等)。
类似3.1方式。
代码示例:
window.open('/xxx/download?downloadType=3');
如果需要参数,就以query方式拼接到url后。如?downloadType=1&businessType=2;
请求只能是get方式。
表现形式:
1、加'_blank'参数
点击下载按钮,执行上述代码,浏览器地址栏打开新页签,识别到后台此地址返回的数据后,页面开始进行下载(浏览器左下角出现下载进度栏,可以选在下载完成后打开文件),下载完毕后浏览器自动关闭页签。
因为'_blank'是默认参数,所以加不加表现形式一样。
优势:代码简单,一句代码即可实现下载功能。
不足:
1、图片、pdf、doc、网页等资源会直接加载(预览)页面(当前页面变成相应资源---相当于直接访问资源链接),当前页面会变成资源页面,严重影响用户体验;
如:window.open('https://www.runoob.com/jsref/met-win-open.html'),会把当前页面替换成目标页面。
2、无法处理成功和失败,无法给用户反馈(加loading、弹窗等)。
使用js原生xhr实现下载文件。
优势:页面中可以直接使用,不需要安装额外的npm包、js库等,属于js原生api,浏览器支持情况较好。可以使用get、post等请求方式。
不足:
1、无法精准提示失败信息。在357行,判断接口返回的错误信息后({"code":1,"msg":"服务异常","data":null}),无法进一步获取具体返回信息,会报错。
只能是自定义提示,如 alert('下载失败');
2、打印x.reponse,是Blob {size: 43, type: 'application/json'}
3、打印x.responseText,会报错admin-rank-detail.vue:360 Uncaught DOMException: Failed to read the 'responseText' property from 'XMLHttpRequest': The value is only accessible if the object's 'responseType' is '' or 'text' (was 'blob').无法获取后台返回的reponse信息,就无法提示msg("服务异常")。
4、使用a标签的download属性下载文件,会有download本身的兼容性问题。如果资源不是同源的,会有兼容性。有张鑫旭大神的总结贴了解HTML/HTML5中的download属性可以参考。
主要逻辑: 1、responseType: 'blob',接口响应类型要设置为'blob';
2、在then里处理返回。
3、通过使用读取文件的方式,用try catch语法判断解析对象是否成功,知道后端返回的是一个错误对象(JSON对象)还是文件流。
优势:可以方便的在请求前后加处理(加loading、弹窗提示等)。可以精准提示接口返回的错误信息。可以使用get、post等请求方式。
不足:需要下载axios的npm包。使用读取文件的方式。用try catch语法处理读取成功和读取失败,不友好。
4、使用a标签的download属性下载文件,会有download本身的兼容性问题。如果资源不是同源的,会有兼容性。有张鑫旭大神的总结贴了解HTML/HTML5中的download属性可以参考。
主要逻辑: 1、responseType: 'blob',接口响应类型要设置为'blob';
2、在第一个then里处理返回。第二个then里处理在a标签download下载文件阶段出现的错误。
3、通过判断返回头部content-type是否有'application/json',知道后端返回的是一个错误对象(JSON对象)还是文件流。
优势:
1、使用fetch下载文件,主流浏览器支持情况较好。
2、是W3C 的正式标准,可以直接使用,不用安装npm包。
3、可以方便的在请求前后加处理(加loading、弹窗提示等)。
4、使用简单,可以做到接口失败处理,能够精准提示接口返回的错误信息。
5、可以使用get、post等请求方式。
不足:
res.json()、res.text()、res.blob()三种读取response返回数据的方法只能读取一次。再次读取会报错如下: Uncaught (in promise) TypeError: Failed to execute 'json' on 'Response': body stream already read。
1、fetch()发出请求以后,只有网络错误或者无法连接时,fetch()才会报错,其他情况(不管接口是超时还是code:1等错误处理)都不会报错:返回status:200,认为请求成功。 所以上图是在第一个else中(即res.status===200)中通过判断content-type是否有'application/json',知道后端返回的是一个错误对象(JSON对象)还是文件流。
2、使用a标签的download属性下载文件,会有download本身的兼容性问题。如果资源不是同源的,会有兼容性。有张鑫旭大神的总结贴了解HTML/HTML5中的download属性可以参考。
对比标题3的五种下载方式,可以看到,3.1和3.2方式一样,都是一句代码实现下载。但是无法实现对请求前后的处理。后三种方式类似,最后都是借助于a标签的download属性进行下载,可以友好的进行请求前后的处理。
1、后台返回二进制数据,将二进制数据变成文件?
就是通过URL.createObjectURL
方法,生成对应二进制数据blob
对象的URL,然后通过动态添加a标签的方法,来实现生成文件。
2、重点是a
标签的download
属性,这个属性是HTML5
新增的。
它的作用是指定下载的文件名,让前端人员可以自定义文件名。如果不指定,那么下载的文件名就会根据请求内容的Content-Disposition
来确定,如果没有Content-Disposition
,那么就会使用请求的URL
的最后一部分作为文件名。
实际项目中可以参考这几种下载文件的方式,根据实际情况使用。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。