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导出)
导出文件流下载,拦截器统一处理配置 需求以往实现的方法(各自的业务层写方法)现在实现的方法(axios里拦截器统一配置处理)把文章链接复制粘贴给后端,让大佬自己赏阅。 需求 之前实现的导出都是各自的业务层…...
山东省图书馆典藏《乡村振兴战略下传统村落文化旅游设计》鲁图中大许少辉博士八一新书
山东省图书馆《乡村振兴战略下传统村落文化旅游设计》鲁图中大许少辉博士八一新书...
2023-08-19力扣每日一题-水题/位运算解法
链接: 2235. 两整数相加 题意: ab 解: ab 补一个位运算写法,进位是(a&b)<<1,不进位的计算结果为a^b 实际代码: #include<iostream> using namespace std; int sum(int num1, int n…...
Hadoop学习:深入解析MapReduce的大数据魔力之数据压缩(四)
Hadoop学习:深入解析MapReduce的大数据魔力之数据压缩(四) 4.1 概述1)压缩的好处和坏处2)压缩原则 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无论是惰性删除还是定期删除,都可能存在删除不尽的情况,无法删除完全,比如每次删除完过期的 key 还是超过 25%,且这些 key 再也不会被客户端访问。 这样的话,定期删除和堕性删除可能都彻底的清理掉。如果…...
Kotlin 高阶函数详解
高阶函数 在 Kotlin 中,函数是一等公民,高阶函数是 Kotlin 的一大难点,如果高阶函数不懂的话,那么要学习 Kotlin 中的协程、阅读 Kotlin 的源码是非常难的,因为源码中有太多高阶函数了。 高阶函数的定义 高阶函数的…...
DL——week2
要学明白的知识点: np.dot()的作用 两个数组的点积,即对应元素相乘 numpy.dot(a,b,outNone) a: ndarray 数组 b: ndarray 数组 out: ndarray, 可选,用来保存dot()的计算结果 numpy Ndarray对象 N维数组对象ndarray&am…...
如何撰写骨灰级博士论文?这是史上最全博士论文指导!
博士论文的写作是博士研究生主要要完成的工作。由于存在着较高的难度,较长的写作周期,以及在创新,写作规范,实际及理论意义等方面有着比较高的要求,博士论文的完成一般说来是有相当难度的。一篇好的博士论文不仅是一本…...
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函数用于判断一个字符串是否包含指定的子字符串,返回一个布尔值(True或False)。 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. 自定义数据集示例:实现一个简…...
Atlas 元数据管理
Atlas 元数据管理 1.Atlas入门 1.1概述 元数据原理和治理功能,用以构建数据资产的目录。对这个资产进行分类和管理,形成数据字典。 提供围绕数据资产的协作功能。 表和表之间的血缘依赖 字段和字段之间的血缘依赖 1.2架构图 导入和导出࿱…...
编程题练习@8-23
分享8月23日两道编程题: 1 开幕式排列 题目描述 导演在组织进行大运会开幕式的排练,其中一个环节是需要参演人员围成一个环形。 演出人员站成了一圈,出于美观度的考虑,导演不希望某一个演员身边的其他人比他低太多或者高太多。 现…...
static相关知识点详解
文章目录 一. 修饰成员变量二. 修饰成员方法三. 修饰代码块四. 修饰类 一. 修饰成员变量 static 修饰的成员变量,称为静态成员变量,该变量不属于某个具体的对象,是所有对象所共享的。 public class Student {private String name;private sta…...
Redisson 分布式锁
Redis是基础客户端库,可用于执行基本操作。 Redisson是基于Redis的Java客户端,提供高级功能如分布式锁、分布式集合和分布式对象。 Redisson提供更友好的API,支持异步和响应式编程,提供内置线程安全和失败重试机制。 实现步骤…...
继承(C++)
继承 一、初识继承概念“登场”语法格式 继承方式九种继承方式组合小结(对九种组合解释) 二、继承的特性赋值转换 一一 切片 / 切割作用域 一一 隐藏 / 重定义 三、派生类的默认成员函数派生类的默认成员函数1. 构造函数2. 拷贝构造3. 赋值运算符重载4. …...
文心一言 VS 讯飞星火 VS chatgpt (80)-- 算法导论7.4 5题
五、如果用go语言,当输入数据已经“几乎有序”时,插入排序速度很快。在实际应用中,我们可以利用这一特点来提高快速排序的速度。当对一个长度小于 k 的子数组调用快速排序时,让它不做任何排序就返回。当上层的快速排序调用返回后&…...
SpringCloud 概述
文章目录 SpringCloud 概述一、微服务中的相关概念1、服务注册与发现2、负载均衡3、熔断4、链路追踪5、API网关 二、SpringCloud的介绍三、SpringCloud的架构1、SpringCloud中的核心组件(1)Spring Cloud Netflix组件(2)Spring Clo…...
Apache ShenYu 学习笔记一
1、简介 这是一个异步的,高性能的,跨语言的,响应式的 API 网关。 官网文档:Apache ShenYu 介绍 | Apache ShenYu仓库地址:GitHub - apache/shenyu: Apache ShenYu is a Java native API Gateway for service proxy, pr…...
uniapp 禁止遮罩层下的页面滚动
使用 touchmove.stop.prevent"toMoveHandle" 事件修饰符 若需要禁止蒙版下的页面滚动,可使用 touchmove.stop.prevent"moveHandle",moveHandle 可以用来处理 touchmove 的事件,也可以是一个空函数。将这个方法直接丢到弹…...
【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型
摘要 拍照搜题系统采用“三层管道(多模态 OCR → 语义检索 → 答案渲染)、两级检索(倒排 BM25 向量 HNSW)并以大语言模型兜底”的整体框架: 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后,分别用…...
docker详细操作--未完待续
docker介绍 docker官网: Docker:加速容器应用程序开发 harbor官网:Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台,用于将应用程序及其依赖项(如库、运行时环…...
以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:
一、属性动画概述NETX 作用:实现组件通用属性的渐变过渡效果,提升用户体验。支持属性:width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项: 布局类属性(如宽高)变化时&#…...
大型活动交通拥堵治理的视觉算法应用
大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动(如演唱会、马拉松赛事、高考中考等)期间,城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例,暖城商圈曾因观众集中离场导致周边…...
解锁数据库简洁之道:FastAPI与SQLModel实战指南
在构建现代Web应用程序时,与数据库的交互无疑是核心环节。虽然传统的数据库操作方式(如直接编写SQL语句与psycopg2交互)赋予了我们精细的控制权,但在面对日益复杂的业务逻辑和快速迭代的需求时,这种方式的开发效率和可…...
微信小程序 - 手机震动
一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注:文档 https://developers.weixin.qq…...
Nuxt.js 中的路由配置详解
Nuxt.js 通过其内置的路由系统简化了应用的路由配置,使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...
JDK 17 新特性
#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持,不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的ÿ…...
项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)
Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败,具体原因是客户端发送了密码认证请求,但Redis服务器未设置密码 1.为Redis设置密码(匹配客户端配置) 步骤: 1).修…...
AGain DB和倍数增益的关系
我在设置一款索尼CMOS芯片时,Again增益0db变化为6DB,画面的变化只有2倍DN的增益,比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析: 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...
