1. axios 请求二进制流文件导出文件

  下载的时候需要传请求头时,普通的 window.location.href=url、window.open(url) 就不适用了。通过 axios 设置服务器响应的数据类型,可以下载后台返回的二进制流文件。

`responseType` 表示服务器响应的数据类型,可以是 'arraybuffer', 'blob', 'document', 'json', 'text', 'stream'

1.1 后台返回的二进制流: 

vue2 axios 文件流下载_vue

因为我这里用到的比较多,所在封装在的公共函数中:

1. const exportExcel = function(url, params={}){
2. axios.get(url,{ params:params, responseType: 'arraybuffer'}).then(function(res){
3. console.log("返回的二进制流文件", res )
4. if(!res) return;
5. //fileName:下载的文件名
6. var fileName = decodeURIComponent(res.headers["content-disposition"].split("=")[1])
7. let blob = new Blob([res.data], {type: 'application/vnd.ms-excel;charset=utf-8'});
8. 9. // 针对ie浏览器
10. if (window.navigator && window.navigator.msSaveOrOpenBlob) {
11. window.navigator.msSaveOrOpenBlob(blob, fileName);
12. } else {
13. //非ie浏览器
14. var downloadElement = document.createElement("a");
15. var href = window.URL.createObjectURL(blob); //常见下载的链接
16. downloadElement.href = href;
17. downloadElement.download = fileName; //下载后文件名
18. document.body.appendChild(downloadElement);
19. downloadElement.click(); //点击下载
20. document.body.removeChild(downloadElement); //下载完成移除元素
21. window.URL.revokeObjectURL(href); //释放blob对象
22. }
23. }).catch(function(error){
24. console.log(error);
25. })
26. }
27. 28. export default {exportExcel}

1.2 使用:


1. <el-button type="primary" plain size="mini" icon="el-icon-download" @click="exportFile">导出</el-button>
2. 3. methods:{
4. //导出
5. exportFile(){
6. exportExcel("/api/warehouse/exportDetailsWarehouse", this.searchForm); //本地测试
7. }
8. }

1.3 需要注意以下几点:

  1. res 的返回值,很多人封装 axios 时直接返回了res.data,上面代码中的 res.data 改为 res 就好了。
let blob = new Blob([res], {type: 'application/vnd.ms-excel;charset=utf-8'});
  1. 但是如果后台在接口里面返回了文件名,是获取不到的,因为只能获取到 res.data 的内容。
  2. 本地调试时,做好跨域代理,否则会报跨域问题。
  3. post 请求可能会失败。

    以上是我在做这个需求时碰到的问题,有的人可能在项目中安装了 mockjs,导致下载失败,


2. 关于 arraybuffer 和 blob

    在参考博客时,发现对于 responseType 有的是填“blob”,有的是 “arraybuffer”,因此去了解了一下这两个的区别。

2.1 ArrayBuffer 和 blob

ArrayBuffer 对象用来表示通用的、固定长度的原始二进制数据缓冲区。 它是一个字节数组,通常在其他语言中称为“byte array”。 你不能直接操作 ArrayBuffer 的内容,而是要通过类型数组对象或 DataView 对象来操作,它们会将缓冲区中的数据表示为特定的格式,并通过这些格式来读写缓冲区的内容。

Blob 对象表示一个不可变、原始数据的类文件对象。它的数据可以按文本或二进制的格式进行读取,也可以转换成 ReadableStream 来用于数据操作。 Blob 表示的不一定是JavaScript原生格式的数据。File 接口基于Blob,继承了 blob 的功能并将其扩展使其支持用户系统上的文件。 要从其他非blob对象和数据构造一个 Blob,使用 Blob() 构造函数。要创建一个 blob 数据的子集 blob,使用 slice() 方法。

2.2 区别

ArrayBuffer对象用来表示通用的、固定长度的原始二进制数据缓冲区。
Blob (binary large object),他表示一个不可变、原始数据的类文件对象,
blob类型只有slice方法,用于返回一个新的 Blob对象,包含了源 Blob对象中指定范围内的数据。
对比发现,ArrayBuffer的数据,是可以按照字节去操作的,而Blob的只能作为一个整的对象去处理。
所以说,ArrayBuffer相比Blob更接近真实的二进制,更底层。

    ArrayBuffer 和 Blob一样,都是二进制数据的容器,而ArrayBuffer相比更为底层,他可以去操作去修改这些二进制值,这两者之间也是可以互转的。

2.3 相互转换


1. // arraybuffer转blob很方便,作为参数传入就行了。
2. var buffer = new ArrayBuffer(16)
3. var blob = new Blob([buffer])
 
1. //此处需要借助fileReader对象:
2. var blob = new Blob([1,2,3,4,5])
3. var reader = new FileReader()
4. reader.onload = function() {
5. console.log(this.result)
6. }
7. reader.readAsArrayBuffer(blob)
8. // 控制台输出的则是ArrayBuffer的数据了

        我这里用的 arraybuffer,改为 “blob” 也能正常下载。

vue2 axios 文件流下载_文件_02

responseType: arraybuffer 请求到的数据

vue2 axios 文件流下载_vue_03

responseTyle:blob 请求到的数据