vue导出文件流获取附件名称并下载(在response.headers里解析filename导出)

这篇具有很好参考价值的文章主要介绍了vue导出文件流获取附件名称并下载(在response.headers里解析filename导出)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

需求

  之前实现的导出都是各自的业务层,调用接口,使用blob对象转换,最终a标签导出,需要自定义文件名跟文件后缀。
  现在统一在拦截器配置,根据后端返回的response.headers解析是否是文件流,统一做配置处理,然后对后端返回的filename进行转码,后端统一配置文件名及类型。前端只管a标签下载即可。

以往实现的方法(各自的业务层写方法)

//数据导出
    indexExport() {
      let statYear = {
        statDate: this.form.statDate,
        dataType: "1",
      };
      let infoMsg = this.$notify.info({
        title: "消息",
        message: "正在下载文件,勿退出,请稍后",
        duration: 0,
      });
      gljyjcDataExport(statYear).then((res) => {
        infoMsg.close(); //下载成功,等待下载提示框关闭
        this.$notify({
          title: "成功",
          message: "下载完成",
          type: "success",
        });
        let blob = new Blob([res], {
          type: "",
        });
        let url = window.URL.createObjectURL(blob);
        const link = document.createElement("a"); // 创建a标签
        link.href = url;
        link.download = "数据清单(" + this.form.statDate + ").xlsx"; // 重命名文件
        link.click();
        URL.revokeObjectURL(url); // 释放内存
      });
    },

现在实现的方法(axios里拦截器统一配置处理)

主要看注释行“文件下载”,因为后端返回流文件时候携带的response.headers会多Content-Disposition这个字段。然后拿到里边的filename后,对filename包含的信息进行转码就可
decodeURIComponent、decodeURI都可进行转码,具体二者有啥区别,水平有限没大看懂,可自行百度查阅符合选项

//拦截器里肯定有请求拦截代码axios.interceptors.request。怕展示代码冗余就不多贴了
...
axios.interceptors.response.use(
    response => {
    
        const res = response.data;
        const config = response.config;
        console.log(response.headers,"response.headers")//这块可以看一下response.headers究竟是什么
        // 文件下载(主要看这块)
        if (response.headers['content-disposition']) {
            let downLoadMark = response.headers['content-disposition'].split(';');
            if (downLoadMark[0] === 'attachment') {
                // 执行下载
                let fileName = downLoadMark[1].split('filename=')[1];
                if (fileName) {
                    //fileName = decodeURIComponent(filename);//对filename进行转码
                    fileName = decodeURI(fileName);
                    if (window.navigator.msSaveOrOpenBlob) {
                        navigator.msSaveBlob(new Blob([res]), fileName);
                    } else {
                        let url = window.URL.createObjectURL(new Blob([res]));
                        let link = document.createElement('a');
                        link.style.display = 'none';
                        link.href = url;
                        link.setAttribute('download', fileName);
                        document.body.appendChild(link);
                        link.click();
                        return;
                    }
                } else {
                    return res;
                }
            }
        }

        // 全局异常处理(获取code做正常的拦截操作,根据自己的业务层code写符合的就可)
        if (res.code !== CODE_SUCCESS) {
            if (res.code == '205') {
                Message.error({ message: res.data || "登录失败" });
                store.dispatch("user/logout").then(() => {
                    window.location.reload();
                  });
                return
            }
            if (res.code === WARN_TIP) {
                Message.warning({
                    message: res.message
                });
            }

            if (res.code === LOGIN_FAIL) {
                Message.error({ message: res.message || "登录失败" });
            }
            // 其他状态码特殊处理
            return Promise.reject(new Error(res.message || "Error"));
        }

        return res;
    }, error => {
        // 防重复提交
        if (error.message) {
            allowRequest(reqList, error.message.url);
        }
        if (error.response) {
            if (error.response.data.code == 600 && !tipCode) {
                tipCode = true;
                Message.error({ message: '系统登录身份令牌失效,请重新登录!' });
            } else if (error.response.status == 500) {
                Message.error({ message: '系统异常' });
            }
        }
        return Promise.reject(error);
    }
);

vue导出文件流获取附件名称并下载(在response.headers里解析filename导出),vue,vue.js,前端,javascript
vue导出文件流获取附件名称并下载(在response.headers里解析filename导出),vue,vue.js,前端,javascript

以上是未解析之前浏览器看到的文件夹名
经过decodeURIComponent或decodeURI解析后,前端就能获取到后端返回的中文文件名了。

vue导出文件流获取附件名称并下载(在response.headers里解析filename导出),vue,vue.js,前端,javascript

把文章链接复制粘贴给后端,让大佬自己赏阅。

截止目前,前端能干的活就到此为止了。
那么有人就想问了,那后端response.headers里没返回我想要的Content-Disposition,前端怎么捕获。
对此呢,我又找我们后端大佬要了一下后端实现的代码,我就原封不动贴出来了,因为我根本看不懂说的是什么意思

Controller端代码(啥是Controller,根本不懂)
 @PostMapping(value="/exportAddresses")
    public Result exportAddresses(HttpServletResponse response){
        String[] titles = new String[] {"id","tableCode","columnName"};
        List<Map<String,Object>> objList = new ArrayList<>();
        DownLoadFileController addressService;
        List<NpColumns> npColumnsList = npColumnsService.findByTableCode("APP_TASK_CASE_INFO");
        for(NpColumns item : npColumnsList){
            Map<String,Object> tempMap = new HashMap<>();
            tempMap.put("id", item.getId());
            tempMap.put("tableCode", item.getTableCode());
            tempMap.put("columnName", item.getColumnName());
            objList.add(tempMap);
        }
        try {
            FileUtils.exportExcel(response,"地址树",titles,objList);
            return ResultGenerator.genSuccessResult("导出成功!");
        }catch (Exception e){
            e.printStackTrace();
            return ResultGenerator.genFailResult("导出失败!");
        }
    }
工具类方法(啥是工具类,也不懂)
public static void exportExcel(HttpServletResponse response,String fileName,String[] titles,List<Map<String,Object>> result){
        HSSFWorkbook wb;
        OutputStream output = null;
        String tempName = fileName;
        try {
            Date date = new Date();
            SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
            fileName +="_"+df.format(date)+".xls";
            String encodedFilename = URLEncoder.encode(fileName, "UTF-8");
            wb= new HSSFWorkbook();
            HSSFSheet sh = wb.createSheet();
            // 设置列宽
            for(int i = 0; i < titles.length-1; i++){
                sh.setColumnWidth( i, 256*15+184);
            }
            // 第一行表头标题,CellRangeAddress 参数:行 ,行, 列,列
            HSSFRow row = sh.createRow(0);
            HSSFCell cell = row.createCell(0);
            cell.setCellValue(new HSSFRichTextString(tempName));
            //cell.setCellStyle(fontStyle(wb));
            sh.addMergedRegion(new CellRangeAddress(0, 0, 0,titles.length-1));
            // 第二行
            HSSFRow row3 = sh.createRow(1);
            // 第二行的列
            for(int i=0; i < titles.length; i++){
                cell = row3.createCell(i);
                cell.setCellValue(new HSSFRichTextString(titles[i]));
                //cell.setCellStyle(fontStyle(wb));
            }
            //填充数据的内容  i表示行,z表示数据库某表的数据大小,这里使用它作为遍历条件
            int i = 2, z = 0;
            while (z < result.size()) {
                row = sh.createRow(i);
                Map<String,Object> map = result.get(z);
                for(int j=0;j < titles.length;j++) {
                    cell = row.createCell(j);
                    if(map.get(titles[j]) !=null) {
                        cell.setCellValue(map.get(titles[j]).toString());
                    }else {
                        cell.setCellValue("");
                    }
                }
                i++;
                z++;
            }
            output = response.getOutputStream();
            response.reset();
            response.addHeader("Content-Type","application/octet-stream;charset=utf-8");
            response.setHeader("Content-disposition", "attachment; filename="+encodedFilename);
            response.setContentType("application/msexcel");
            wb.write(output);
            output.flush();
            output.close();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
最后还有个中文处理乱码那块(这都是啥啥啥,还是不懂)
String encodedFilename = URLEncoder.encode(fileName, "UTF-8");设置文件名的中文编码
response.addHeader("Content-Type","application/octet-stream;charset=utf-8");//这里也设置了相同的编码格式
response.setHeader("Content-disposition", "attachment; filename="+encodedFilename);

大家有更好的实现方案话欢迎多交流文章来源地址https://www.toymoban.com/news/detail-660395.html

到了这里,关于vue导出文件流获取附件名称并下载(在response.headers里解析filename导出)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • Spring Boot学习随笔- 文件上传和下载(在线打开、附件下载、MultipartFile)

    Spring Boot学习随笔- 文件上传和下载(在线打开、附件下载、MultipartFile)

    学习视频:【编程不良人】2021年SpringBoot最新最全教程 文件上传是指将文件从客户端计算机传输到服务器的过程。 上传思路 前端的上传页面:提交方式必须为 post , enctype 属性必须为 multipart/form-data 开发后端的Controller 后端方法接收参数必须和前端标签的name名一致 upload.js

    2024年02月04日
    浏览(21)
  • uniapp下载附件保存到手机(文件、图片)ios兼容

    downloadFile(file) ,其中 file 为下载的文件地址 uni.downloadFile 图片 使用 uni.saveImageToPhotosAlbum 【安卓、ios都合适】 文件 使用 uni.openDocument 【安卓图片也可以用这个,ios会失败】

    2024年02月06日
    浏览(8)
  • java实现浏览器下载附件时文件名中文乱码解决方案

    方案一:URLEncoder 解决 IE 和 谷歌浏览器的附件中文名问题。 如果客户端浏览器是 IE 浏览器 或者 是谷歌浏览器。我们需要使用 URLEncoder 类先对中文名进行 UTF-8 的编码 操作。 因为 IE 浏览器和谷歌浏览器收到含有编码后的字符串后会以 UTF-8 字符集进行解码显示。 方案二:B

    2024年03月09日
    浏览(32)
  • vue前端获取项目下的静态资源文件夹中的文件并下载

    vue前端获取项目下的静态资源文件夹中的文件并下载

    前端项目/public/static/image文件夹下,两张图片,因为不会经常改变所以做成静态资源 从项目中获取这两张图片 html: 前端项目的 publicstaticfaultFile文件夹中放入模板文件: 实现效果: 代码: 前端下载使用 a 标签的自带的download下载 参考文章:require.context()的用法详解

    2024年02月12日
    浏览(35)
  • vue 中从后端获取到文件的 url 地址,前端根据 url 地址下载文件

    vue 中从后端获取到文件的 url 地址,前端根据 url 地址下载文件

    项目用的是 vben admin 框架,用的是 vue3 + TS 项目需求数据导出功能,前端需要实现文件下载功能 后端返回的是文件的 url 地址 (本项目中返回的是阿里云 oss 的文件地址) 从后端得到的是一个 url 地址,先通过 fetch api 请求这个 url 地址并转换成 blob 对象,通过 URL.createObjectUrl() 将 blo

    2024年02月06日
    浏览(8)
  • Java获取文件的后缀名称

        使用lastIndexOf()方法,找到文件名中最后一个点的位置,     然后使用substring()方法,获取点后面的字符串作为文件后缀名。 参考:java获取文件后缀名怎么操作_千锋教育

    2024年01月21日
    浏览(2)
  • 【java】如何获取整个文件夹的文件名称

    需求 有时候我们需要一个文件夹里的所有文件的名称我们只能截图,然后再使用微信提取出其中的文字,这样是比较麻烦的,今天给大家介绍使用java提取所有文件的名字,代码如下:

    2024年02月14日
    浏览(30)
  • 【前端】根据后端返回的url进行下载并设置文件下载名称

            在我们项目当中存储文件是存储到厂商的服务器上的,然后厂商返回一个可以直接下载url地址,但是前端使用这个url下载的时候永远都是保存一个名字,这时候我们就需要设置文件保存的名称,         那么如何实现呢?使用了fetch将url转换成了blob即可。 代码

    2024年02月04日
    浏览(12)
  • Request Headers和Response Headers中的Content-Type以及ResponseType

    Request Headers和Response Headers中的Content-Type以及ResponseType

    HTTP请求响应过程中的Content-type你真的清楚吗 详解get与post请求方式、content-type与responseType、@Requestbody与@Requestparam的使用场景 axios配置请求头content-type浅谈 HTTP 请求头中的Content-Type类型 背景: Request Headers中的Content-Type: XMLHttpRequest 的 responseType 属性 Response Headers中的Content-Type R

    2024年02月13日
    浏览(9)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包