在后盾管理系统中,咱们常常会遇到文件导出这个需要,上面,我将几种常见的导出形式做一个简略的介绍,让大家在当前遇到此类需要时,可能切合实际状况,采取绝对正当的形式。
导出指标
文件地址
曾经存在服务器上的文件,比方用户上传的图片、资料等等http://192.168.1.103:3000/imgs/bg.jpg
导出接口
依据用户需要,动静生成的文件,常见的比方导出业务流水表格,数据汇总表格等等http://192.168.1.103:3000/api/export
导出形式
a.download
html5新增的属性
文件名由前端指定,前台下达保留指令
毛病:ie不反对,并且,在跨域时,即便后盾设置了容许跨域的响应头,也无奈下载,也就是说,必须与以后域统一
<a href="http://192.168.1.103:3000/imgs/xx.jpg" download /><a href="http://192.168.1.103:3000/imgs/xx.jpg" download="xx.jpg" />
ajax + a.download
文件名由前台指定,前台下达保留指令
将后盾返回的二进制数据,转换成blob,而后利用URL.createObjectURL,创立一个指向内存中blob的URL,再应用a标签的download属性进行导出
毛病:ie不反对,blob有内存限度
然而防止了独自应用a.download必须与域名统一的问题
function useLinkDownload(url, fileName) { const link = document.createElement("a"); link.style.display = "none"; link.href = url; link.download = fileName; document.body.appendChild(link); link.click(); document.body.removeChild(link);}$.get('http://192.168.1.103:3000/api/export', { responseType: 'blob' }) .then(function(res) { // 创立一个指向内存中blob的URL const objectURL = URL.createObjectURL(res.data); useLinkDownload(objectURL, 'xx.xlsx') URL.revokeObjectURL(objectURL) })
ajax + msSaveBlob
文件名由前台指定,前台下达保留指令
ie专有api
毛病:chrome、firefox不反对,blob有内存限度
$.get('http://192.168.1.103:3000/api/export', { responseType: 'blob' }) .then(function(res) { navigator.msSaveBlob(res.data, "xx.xlsx"); })
content-disposition
文件名由后盾指定,此种形式指定的文件名优先级高于a.download
前端发送申请即可,须要留神的一点是,不能与ajax组合(应用ajax后,会变成二进制流,须要前端对流解决)
var url = 'http://192.168.1.103:3000/api/export'
a标签
function useLink(url) { const link = document.createElement("a"); link.style.display = "none"; link.href = url; document.body.appendChild(link); link.click(); document.body.removeChild(link);}useLink(url)
location.href
function useLocationDownload(url) { window.location.href = url;}useLocationDownload(url)
window.open
function useWindowOpenDownload(url) { window.open(url);}useWindowOpenDownload(url)
form
function useFormDownload(url) { const form = document.createElement("form"); form.action = url; form.method = "get"; form.style.display = "none"; document.body.appendChild(form); form.submit(); form.remove();}useFormDownload(url)
iframe
function useIframeDownload(url) { const iframe = document.createElement("iframe"); iframe.src = url; iframe.style.display = "none"; document.body.appendChild(iframe); document.body.removeChild(iframe);}useIframeDownload(url)
一些问题
跨域
a.download有效,即便后盾设置了Access-Control-Allow-Origin也有效,download的值须要与以后域名统一,让ngnix进行转发能够解决。
https://html.spec.whatwg.org/dev/links.html#downloading-resources
大文件
ajax的形式须要用到blob,而blob是有限度的,例如chrome的下限是2GB,所以ajax的形式须要被排除,可选的形式是a.download和Content-Disposition,这两种形式没有用到blob,所以也没有具体的限度。
在应用a标签或者form时,为了防止在导出时产生页面闪动景象,咱们能够应用target非_self的值,来防止,然而当target为_self时,如果导出申请失败了,页面会被笼罩掉,用哪种形式能够防止这个问题?
可选的形式为ajax和iframe,这两者都能够防止失败时笼罩掉以后页面,并且ajax还能够通知用户失败的起因
总结
默认状况下,浏览器面对本身无奈关上的文件,都会采取将其保留到本地形式,然而如图片,文本文件以及 pdf,浏览器首先尝试关上,这在个别状况下是正当的,但当咱们的目标是保留而不是关上时,这就会变成一个问题。
上文列举了几种导出形式以及各自的局限性,综合来看 Content-Disposition 应该是比拟通用的形式,即兼顾了兼容性,也防止了浏览器内存限度。
材料
https://github.com/eligrey/FileSaver.js/wiki/Saving-a-remote-file#using-http-header