当前位置: 首页 > news >正文

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

导出文件流下载,拦截器统一处理配置

  • 需求
  • 以往实现的方法(各自的业务层写方法)
  • 现在实现的方法(axios里拦截器统一配置处理)
  • 把文章链接复制粘贴给后端,让大佬自己赏阅。

需求

  之前实现的导出都是各自的业务层,调用接口,使用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);}
);

在这里插入图片描述
在这里插入图片描述

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

在这里插入图片描述

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

截止目前,前端能干的活就到此为止了。
那么有人就想问了,那后端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);

大家有更好的实现方案话欢迎多交流

相关文章:

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

导出文件流下载&#xff0c;拦截器统一处理配置 需求以往实现的方法&#xff08;各自的业务层写方法&#xff09;现在实现的方法&#xff08;axios里拦截器统一配置处理&#xff09;把文章链接复制粘贴给后端&#xff0c;让大佬自己赏阅。 需求 之前实现的导出都是各自的业务层…...

​山东省图书馆典藏《乡村振兴战略下传统村落文化旅游设计》鲁图中大许少辉博士八一新书

​山东省图书馆《乡村振兴战略下传统村落文化旅游设计》鲁图中大许少辉博士八一新书...

2023-08-19力扣每日一题-水题/位运算解法

链接&#xff1a; 2235. 两整数相加 题意&#xff1a; ab 解&#xff1a; ab 补一个位运算写法&#xff0c;进位是(a&b)<<1&#xff0c;不进位的计算结果为a^b 实际代码&#xff1a; #include<iostream> using namespace std; int sum(int num1, int n…...

Hadoop学习:深入解析MapReduce的大数据魔力之数据压缩(四)

Hadoop学习&#xff1a;深入解析MapReduce的大数据魔力之数据压缩&#xff08;四&#xff09; 4.1 概述1&#xff09;压缩的好处和坏处2&#xff09;压缩原则 4.2 MR 支持的压缩编码4.3 压缩方式选择4.3.1 Gzip 压缩4.3.2 Bzip2 压缩4.3.3 Lzo 压缩4.3.4 Snappy 压缩4.3.5 压缩…...

LRU淘汰策略执行过程

1 介绍 Redis无论是惰性删除还是定期删除&#xff0c;都可能存在删除不尽的情况&#xff0c;无法删除完全&#xff0c;比如每次删除完过期的 key 还是超过 25%&#xff0c;且这些 key 再也不会被客户端访问。 这样的话&#xff0c;定期删除和堕性删除可能都彻底的清理掉。如果…...

Kotlin 高阶函数详解

高阶函数 在 Kotlin 中&#xff0c;函数是一等公民&#xff0c;高阶函数是 Kotlin 的一大难点&#xff0c;如果高阶函数不懂的话&#xff0c;那么要学习 Kotlin 中的协程、阅读 Kotlin 的源码是非常难的&#xff0c;因为源码中有太多高阶函数了。 高阶函数的定义 高阶函数的…...

DL——week2

要学明白的知识点&#xff1a; np.dot()的作用 两个数组的点积&#xff0c;即对应元素相乘 numpy.dot(a,b,outNone) a: ndarray 数组 b: ndarray 数组 out: ndarray, 可选&#xff0c;用来保存dot&#xff08;&#xff09;的计算结果 numpy Ndarray对象 N维数组对象ndarray&am…...

如何撰写骨灰级博士论文?这是史上最全博士论文指导!

博士论文的写作是博士研究生主要要完成的工作。由于存在着较高的难度&#xff0c;较长的写作周期&#xff0c;以及在创新&#xff0c;写作规范&#xff0c;实际及理论意义等方面有着比较高的要求&#xff0c;博士论文的完成一般说来是有相当难度的。一篇好的博士论文不仅是一本…...

08.SpringBoot请求相应

文章目录 1 请求1.1 Postman1.2 简单参数1.2.1 原始方式1.2.2 SpringBoot方式1.2.3 参数名不一致 1.3 实体参数1.3.1 简单实体对象1.3.2 复杂实体对象 1.4 数组集合参数1.4.1 数组1.4.2 集合 1.5 日期参数1.6 JSON参数1.7 路径参数 2 响应2.1 ResponseBody注解2.2 统一响应结果…...

C#详解-Contains、StartsWith、EndsWith、Indexof、lastdexof

目录 简介: 过程: 举例1.1 举例1.2 ​ 总结: 简介: 在C#中Contains、StarsWith和EndWith、IndexOf都是字符串函数。 1.Contains函数用于判断一个字符串是否包含指定的子字符串&#xff0c;返回一个布尔值&#xff08;True或False&#xff09;。 2.StartsWith函数用于判断一…...

FATE框架中pipline基础教程

目录 1. 用pipline上传数据2. 用 Pipeline 进行 Hetero SecureBoost 的训练和预测3. 用 Pipeline 构建神经网络模型3.1 Homo-NN Quick Start: A Binary Classification Task3.2 Hetero-NN Quick Start: A Binary Classification Task 4. 自定义数据集示例&#xff1a;实现一个简…...

Atlas 元数据管理

Atlas 元数据管理 1.Atlas入门 1.1概述 元数据原理和治理功能&#xff0c;用以构建数据资产的目录。对这个资产进行分类和管理&#xff0c;形成数据字典。 提供围绕数据资产的协作功能。 表和表之间的血缘依赖 字段和字段之间的血缘依赖 1.2架构图 导入和导出&#xff1…...

编程题练习@8-23

分享8月23日两道编程题&#xff1a; 1 开幕式排列 题目描述 导演在组织进行大运会开幕式的排练&#xff0c;其中一个环节是需要参演人员围成一个环形。 演出人员站成了一圈&#xff0c;出于美观度的考虑&#xff0c;导演不希望某一个演员身边的其他人比他低太多或者高太多。 现…...

static相关知识点详解

文章目录 一. 修饰成员变量二. 修饰成员方法三. 修饰代码块四. 修饰类 一. 修饰成员变量 static 修饰的成员变量&#xff0c;称为静态成员变量&#xff0c;该变量不属于某个具体的对象&#xff0c;是所有对象所共享的。 public class Student {private String name;private sta…...

Redisson 分布式锁

Redis是基础客户端库&#xff0c;可用于执行基本操作。 Redisson是基于Redis的Java客户端&#xff0c;提供高级功能如分布式锁、分布式集合和分布式对象。 Redisson提供更友好的API&#xff0c;支持异步和响应式编程&#xff0c;提供内置线程安全和失败重试机制。 实现步骤…...

继承(C++)

继承 一、初识继承概念“登场”语法格式 继承方式九种继承方式组合小结&#xff08;对九种组合解释&#xff09; 二、继承的特性赋值转换 一一 切片 / 切割作用域 一一 隐藏 / 重定义 三、派生类的默认成员函数派生类的默认成员函数1. 构造函数2. 拷贝构造3. 赋值运算符重载4. …...

文心一言 VS 讯飞星火 VS chatgpt (80)-- 算法导论7.4 5题

五、如果用go语言&#xff0c;当输入数据已经“几乎有序”时&#xff0c;插入排序速度很快。在实际应用中&#xff0c;我们可以利用这一特点来提高快速排序的速度。当对一个长度小于 k 的子数组调用快速排序时&#xff0c;让它不做任何排序就返回。当上层的快速排序调用返回后&…...

SpringCloud 概述

文章目录 SpringCloud 概述一、微服务中的相关概念1、服务注册与发现2、负载均衡3、熔断4、链路追踪5、API网关 二、SpringCloud的介绍三、SpringCloud的架构1、SpringCloud中的核心组件&#xff08;1&#xff09;Spring Cloud Netflix组件&#xff08;2&#xff09;Spring Clo…...

Apache ShenYu 学习笔记一

1、简介 这是一个异步的&#xff0c;高性能的&#xff0c;跨语言的&#xff0c;响应式的 API 网关。 官网文档&#xff1a;Apache ShenYu 介绍 | Apache ShenYu仓库地址&#xff1a;GitHub - apache/shenyu: Apache ShenYu is a Java native API Gateway for service proxy, pr…...

uniapp 禁止遮罩层下的页面滚动

使用 touchmove.stop.prevent"toMoveHandle" 事件修饰符 若需要禁止蒙版下的页面滚动&#xff0c;可使用 touchmove.stop.prevent"moveHandle"&#xff0c;moveHandle 可以用来处理 touchmove 的事件&#xff0c;也可以是一个空函数。将这个方法直接丢到弹…...

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…...

docker详细操作--未完待续

docker介绍 docker官网: Docker&#xff1a;加速容器应用程序开发 harbor官网&#xff1a;Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台&#xff0c;用于将应用程序及其依赖项&#xff08;如库、运行时环…...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:

一、属性动画概述NETX 作用&#xff1a;实现组件通用属性的渐变过渡效果&#xff0c;提升用户体验。支持属性&#xff1a;width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项&#xff1a; 布局类属性&#xff08;如宽高&#xff09;变化时&#…...

大型活动交通拥堵治理的视觉算法应用

大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动&#xff08;如演唱会、马拉松赛事、高考中考等&#xff09;期间&#xff0c;城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例&#xff0c;暖城商圈曾因观众集中离场导致周边…...

解锁数据库简洁之道:FastAPI与SQLModel实战指南

在构建现代Web应用程序时&#xff0c;与数据库的交互无疑是核心环节。虽然传统的数据库操作方式&#xff08;如直接编写SQL语句与psycopg2交互&#xff09;赋予了我们精细的控制权&#xff0c;但在面对日益复杂的业务逻辑和快速迭代的需求时&#xff0c;这种方式的开发效率和可…...

微信小程序 - 手机震动

一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注&#xff1a;文档 https://developers.weixin.qq…...

Nuxt.js 中的路由配置详解

Nuxt.js 通过其内置的路由系统简化了应用的路由配置&#xff0c;使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...

JDK 17 新特性

#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持&#xff0c;不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的&#xff…...

项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)

Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败&#xff0c;具体原因是客户端发送了密码认证请求&#xff0c;但Redis服务器未设置密码 1.为Redis设置密码&#xff08;匹配客户端配置&#xff09; 步骤&#xff1a; 1&#xff09;.修…...

AGain DB和倍数增益的关系

我在设置一款索尼CMOS芯片时&#xff0c;Again增益0db变化为6DB&#xff0c;画面的变化只有2倍DN的增益&#xff0c;比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析&#xff1a; 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...