前端vue下载文件时blob返回流中怎么获取文件名

vue

  我很久之前写了一篇前端vue利用blob对象下载文件,有些人私信我,如果后端返回流失败,给出的json对象该怎么获得?前端获取的流怎么能获取原文件名?其实在那篇文章之后,我就已经针对这两个问题进行了优化,于是就有了这篇。

  首先,针对第一个问题,如果能正常获得文件流,前端则以blob对象承接,反之,一般后端会传一个json对象告诉你失败了以及失败原因,这个时候json对象由于请求中responseType: 'blob'的声明之后,也会生成文件,但是文件内容是乱码,这个时候,我们必须要用到FileReader.readAsText():

详细见MDN官方文档关于FileReader.readAsText()的描述:https://developer.mozilla.org/zh-CN/docs/Web/API/FileReader/readAsText。所以上次的代码经过改造是这样子的:

<el-button @click="exportExcel()">导出</el-button>

<script>

methods: {

exportExcel(){

var params={

XX:xx//额外需要携带的请求体

}

this.$axios.get('/XX/XX',{

params: params,

responseType: 'blob' //首先设置responseType字段格式为 blob

}).then(res => {

if(res.type=="application/json"){

let reader = new FileReader();

reader.onload = e =>this.$alert(JSON.parse(e.target.result).xxxx); //xxxx为字段名

reader.readerAsText(res);

}else{

let blob = new Blob([res], {type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8"}); // 为blob设置文件类型,这里以.xlsx为例

let url = window.URL.createObjectURL(blob); // 创建一个临时的url指向blob对象

let a = document.createElement("a");

a.href = url;

a.click();

// 释放这个临时的对象url

window.URL.revokeObjectURL(url);

}

});

},

}

</script>

  然后,我们针对第二个问题,前端获取的流怎么能获取原文件名?有两种解决方案,都得需要后端同事的配合,一种是在点击导出按钮之前,一般这种就是有一个文件列表(表格),前端已经知道文件的位置,然后把文件路径传给后端,由后端到指定目录下取到再传给你。文件上传的时候因为防止文件名重复,后端会对文件进行重命名(采取8位随机字符串+原文件名),在你知道路径的情况下,你就可以直接将文件路径中最后一个"/"后字段进行截取作为文件名。 

<el-button @click="exportExcel()">导出</el-button>

<script>

methods: {

exportExcel(){

var params={

filePath:this.filePath

}

this.$axios.get('/XX/XX',{

params: params,

responseType: 'blob' //首先设置responseType字段格式为 blob

}).then(res => {

if(res.type=="application/json"){

let reader = new FileReader();

reader.onload = e =>this.$alert(JSON.parse(e.target.result).xxxx); //xxxx为字段名

reader.readerAsText(res);

}else{

let blob = new Blob([res], {type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8"}); // 为blob设置文件类型,这里以.xlsx为例

let url = window.URL.createObjectURL(blob); // 创建一个临时的url指向blob对象

let a = document.createElement("a");

a.href = url;

let filePath = this.filePath;

let subFilePath = filePath.split('/');

a.download = subFilePath[subFilePath.length-1].substring(8);

a.click();

// 释放这个临时的对象url

window.URL.revokeObjectURL(url);

}

});

},

}

</script>

  另一种是后端同事先对请求头进行改造,在给前端返回的请求头中添加Content-Dispositon字段。

response.reset();

response.setContentType("application/application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8"); //设置文件类型,这里以.xlsx为例

//设置文件的原文件名,若文件名中含有中文则需要解码,否则会出现乱码

response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(fileName, "utf-8"));

// 这步很关键,需要在给前端返回的请求头中添加Content-Disposition字段

response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");  

f12控制台network中请求头部分

  然后有些人就是在这个地方卡住了,说利用res.headers['content-disposition']取不到Content-Dispositon的值,这是因为这些人都配置了axios拦截器,而且在拦截器里写了相关的处理导致没有返回全部的响应信息。我们在上面代码中.then()回调函数中的res返回前是都要经过axios拦截器处理的,如果没有设置axios拦截器的是可以直接通过res.headers['content-disposition']直接获取到的。

// 添加响应拦截器

axios.interceptors.response.use(response=>{

// 对响应数据做点什么

return response.data; //这里只把这个响应里的data返回回来了,所以取不到headers,想要全部信息就return response;

}, error=>{

// 对响应错误做点什么

return Promise.reject(error);

});

以上是 前端vue下载文件时blob返回流中怎么获取文件名 的全部内容, 来源链接: utcz.com/z/380787.html

回到顶部