ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

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

2022-03-07 17:35:46  阅读:439  来源: 互联网

标签:vue 文件名 url res 流中 let blob response


  我很久之前写了一篇前端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,文件名,url,res,流中,let,blob,response
来源: https://www.cnblogs.com/jdWu-d/p/15513478.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有