往常开发过程中,文件下载的实现都是后端提供一个接口,大多是返回一个Blob对象,然后前端编码实现下载,在这次项目中后端只返回文件的url,需要自己实现下载,突然发现自己连这么基础的问题都解决不了,确实挺离谱的。
通过Blob对象下载 先前说了,往常是通过后端返回一个Blob对象来实现下载功能,如果后端返回的是二进制的文件流,我们需要指定ajax请求的响应类型为blob
先看下后端返回Blob的情况下应该怎么实现下载呢。
1 2 3 4 5 6 7 8 9 10 async downloadFn ( ) { let res = await downLoad(params) let file_name = '文件名称' let save_blob = new Blob([res]) let save_link = document .createElement('a' ) save_link.setAttribute('href' , window .URL.createObjectURL(save_blob)) save_link.setAttribute('download' , file_name) save_link.click() }
就这么简单,关键点就是new Blob和createObjectURL。
注意点是new Blob([data])中的data只能是ArrayBuffer、blob等几种类型,不是所有类型都可以直接放入的。
如果后端不直接返回blob,而是一个文件流,那么需要指定接口的响应类型,其他就同后端直接返回blob一样了
1 2 3 4 5 6 7 8 9 getFile ( ) { return axios({ method : 'post' , url : '' , data : '' , responseType : 'blob' }) }
通过Url实现下载 我们在只有一个url的情况下,我最开始通过简单的a标签想实现这个功能,但是并不是那么可行的。
查阅网上前辈的解决方法,找到了一个学习成本最低的,就是我们通过这个url来得到一个Blob对象,然后就跟前边一样了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 downloadFile (url ) { let file_name = '文件名称' let url2 = url.replace(/\\/g , '/' ) const xhr = new XMLHttpRequest(); xhr.open('GET' , url, true ); xhr.responseType = 'blob' ; xhr.onload = () => { if (xhr.status === 200 ) { saveAs(xhr.response, fileName); } }; xhr.send(); } saveAs (data, name ) { const urlObject = window .URL || window .webkitURL || window ; const export_blob = new Blob([data]); const save_link = document .createElement('a' ) save_link.href = urlObject.createObjectURL(export_blob); save_link.download = name; save_link.click(); }
这个方法呢是先去请求这个url,并将返回的内容格式设置为blob,然后就是一样的new Blob和createObjectURL了。