文件下载是前端一个十分常见的需求,但是系统的设计不同,会采用不同的实现方案,以下就几种情况做说明。
一、下载链接不需要用户认证
这种情况是最简单的,直接使用window的open方法来实现即可。如果不想另外弹出窗口,可以内置一个iframe并隐藏它,然后把链接赋值给iframe的src即可,简单暴力。
二、下载链接需要用户认证
如果系统的用户认证是基于cookie,那么依然可以使用上述方法实现,不赘述。
如果系统的用户认证是基于token,我们在发送下载请求的时候需要传递token,有两种办法
1、挂在url后面作为参数的一部分,这种方法在url里暴露了token,不安全,不推荐
2、使用xhr异步请求来下载,这种方式,我们可以把token放在请求头中,或者参数体中,请求的方法可以是post。
使用axios的方案时,下载的文件常遇到打不开的情况,文件损坏,大小也会翻倍,应该是编码不一致导致,这里我们使用原始的xmlhttprequest来实现,代码如下:
1 var download= function (method, url, data,isDown) { 2 var xhr = new XMLHttpRequest(); 3 xhr.open(method, url, true); 4 xhr.setRequestHeader("token", localStorage.getItem('token')) 5 xhr.responseType = 'blob'; 6 xhr.onload = function() { 7 if (this.status === 200) { 8 var type = xhr.getResponseHeader('Content-Type'); 9 var blob = new Blob([this.response], {type: type}); 10 var filename = xhr.getResponseHeader('content-disposition').replace(/w+;filename=(.*)/, '$1') 11 if (typeof window.navigator.msSaveBlob !== 'undefined') { 12 window.navigator.msSaveBlob(blob, filename); 13 } else { 14 var URL = window.URL || window.webkitURL; 15 var objectUrl = URL.createObjectURL(blob); 16 if (filename) { 17 var a = document.createElement('a'); 18 if (typeof a.download === 'undefined') { 19 window.location = objectUrl; 20 } else { 21 a.href = objectUrl; 22 if(isDown){ 23 a.download = decodeURI(filename); 24 } 25 document.body.appendChild(a); 26 a.click(); 27 a.remove(); 28 } 29 } else { 30 window.location = objectUrl; 31 } 32 } 33 } 34 } 35 xhr.send(JSON.stringify(data)); 36 }