springboot+vue2+elementui+mybatis- 批量导出导入

全部导出

批量导出

报错问题分析

经过排查,原因是因为在发起 axios 请求的时候,没有指定响应的数据类型(这里需要指定响应的数据类型为 blob 二进制文件)

当响应数据回来后,会执行 axios 后置拦截器的代码,因为没有对响应头的类型进行判断,而是判断为字符串 String,将该流转为 JSON 对象而报错

导出的 思路分析:

1. 得到用户选中的 ids 数组(前端 vue)

2. 请求导出的后台接口

3. 根据 id,从数据库中查询记录(springboot)

4.拿到数据之后,使用流的方式,响应给浏览器/客户端

Vue2+Elementui

1.新增导出按钮

<el-button type="primary" @click="exportUsers">批量导出</el-button>

2.将选择的 ids 集合当作参数提交给后端 springboot

    //导出exportUsers() {//如果没有选择行数据,则全部导出或者按照检索条件导出this.$confirm("您是否需要导出?", "提示", {iconClass: "el-icon-question",//自定义图标样式confirmButtonText: "确认",//确认按钮文字更换cancelButtonText: "取消",//取消按钮文字更换showClose: true,//是否显示右上角关闭按钮type: "warning",//提示类型  success/info/warning/error}).then(() => {//确认操作//请求批量导出的接口this.$request.get('/user/exportUsersById', {params: { //ids携带过去,ids: this.ids //存的是勾选的id的数组},responseType: 'blob', // 设置响应类型为blob(响应的数据是二进制文件)paramsSerializer: params => {//get方法,传的参数的是数组解决uri的路径问题 ?ids[]=225&ids[]=226return qs.stringify(params, {indices: false})}}).then(response => {// console.log("response=", response)if (response.size > 0) {//返回的是blob,判断文件的大小this.$message.success("导出成功");} else {this.$message.warning("导出失败");}})}).catch(() => {//取消操作});},

3.在 axios 后置拦截器中将 blob 二进制文件转为 excel

import axios from 'axios'
import router from "@/router";
import {saveAs} from 'file-saver';//导入该依赖// response 拦截器
// 可以在接口响应后统一处理结果
request.interceptors.response.use(response => {//简化.data操作 直接使用res.data就能得到数据let res = response.data;console.log("res=", res)// 判断是否为二进制数据if (response.config.responseType === 'blob') {console.log("该文件是二进制文件")// 从响应头中获取文件名const contentDisposition = response.headers.get('Content-Disposition');const filenameRegex = /filename=(.+)/const fileNameMatch = contentDisposition && contentDisposition.match(filenameRegex);const fileName = fileNameMatch && fileNameMatch[1];// 对文件名进行解码,换原成原始文件名const decodedFileName = decodeURIComponent(fileName);// 对文件名进行解码,换原成原始文件名// const decodedFileName = decodeURIComponent(fileName);// 使用FileSaver库保存文件const blob = new Blob([response.data], {type: response.headers['content-type']});// saveAs(blob, 'file.xlsx');saveAs(blob, decodedFileName || 'file.xlsx');}// // 兼容服务端返回的字符串数据//  if (typeof res === 'string') {//      res = res ? JSON.parse(res) : res//  }// //返回接口的状态码401,返回登录页面// if (res.code === '401') {//     router.push('/login')// }return res;
}, error => {console.error('response error: ' + error) // for debugreturn Promise.reject(error)
})

SpringBoot

导入 maven 依赖

<dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>4.1.2</version>
</dependency>
@RequestMapping("/exportUsersById")
public void exportUsersById(@RequestParam(value = "ids", required = false) List<Integer> ids, HttpServletResponse response) {log.info("idList=" + ids);List<User> userList;// 用户数据集合String fileName = "";// 文件名if (ObjectUtil.isEmpty(ids) || ids.contains(-1)) {// 全部导出userList = UserServiceImpls.list();fileName = "所有用户";log.info("所有用户=" + userList);if (ObjectUtil.isEmpty(userList)) { // 列表为空throw new BizException("用户列表为空");}} else {userList = UserServiceImpls.listByIds(ids);// 批量导出fileName = "部分用户";log.info("部分用户=" + userList);}// 使用huTools工具类-Excel导出ExcelWriter writer = ExcelUtil.getWriter(true);writer.write(userList, true);response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");try {// 将Content-Disposition暴露,前端才能得到Content-Disposition的value值response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "utf-8") + ".xlsx");writer.flush(response.getOutputStream(), true);} catch (IOException e) {// e.printStackTrace();} finally {writer.close();}
}

批量导入

<el-uploadstyle="display: inline-block"action="http://localhost:9000/user/importData":headers="{token:loginUSer.token}":show-file-list="false":on-success="handleFileSuccess"><el-button type="success" class="my-button">批量导入</el-button>
</el-upload>
/*** 导入数据** @param file:* @return ResultResponse<String>* @author "卒迹"* @description TODO* @date 17:32*/@PostMapping("/importData")
public ResultResponse<String> importData(MultipartFile file) throws IOException {// 写入文件流ExcelReader reader = ExcelUtil.getReader(file.getInputStream());// 以User类的格式导入数据-返回1个集合对象,这里取决于alias注解List<User> userList = reader.readAll(User.class);if (ObjectUtil.isEmpty(userList)) {// 导入的数据为空return ResultResponse.error("导入失败");}// 写入数据到数据库boolean isSave = false;try {isSave = UserServiceImpls.saveBatch(userList);} catch (Exception e) {// e.printStackTrace();return ResultResponse.error("导入出错");}return isSave ? ResultResponse.success("导入成功") : ResultResponse.error("导入失败");
}
//导入
handleFileSuccess(response, file, fileList) {console.log("response=", response)if (response.code === "2000") {this.$message.success(response.message);//刷新数据this.queryUserByUsernameOrName(this.isDisplayMsg = false, 1)}if (response.code === "-1") {this.$message.error(response.message);}},

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/803772.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[开源] 基于transformer的时间序列预测模型python代码

分享一下基于transformer的时间序列预测模型python代码&#xff0c;给大家&#xff0c;记得点赞哦 #!/usr/bin/env python # coding: 帅帅的笔者import torch import torch.nn as nn import numpy as np import pandas as pd import time import math import matplotlib.pyplo…

【Java8新特性】二、函数式接口

这里写自定义目录标题 一、什么是函数式接口二、自定义函数式接口三、作为参数传递 Lambda 表达式四、四大内置核心函数式接口1、消费形接口2、供给形接口3、函数型接口4、断言形接口 一、什么是函数式接口 只包含一个抽象方法的接口&#xff0c;称为函数式接口。你可以通过 L…

【MATLAB高级编程】第二篇 | 元胞数组(cell)操作

【第二篇】元胞数组&#xff08;cell&#xff09;操作 1. 创建元胞数组cell2. 查看和修改cell内的元素值3. 高级操作: 可视化作图显示cell内的内容4. 把矩阵转换成单元数组5. 把单元数组转换成结构体变量 你好&#xff01; 欢迎进入 《MATLAB高级编程》 文章系列 &#xff0c;每…

postgresql uuid

示例数据库版本PG16&#xff0c;对于参照官方文档截图&#xff0c;可以在最上方切换到对应版本查看&#xff0c;相差不大。 方法一&#xff1a;自带函数 select gen_random_uuid(); 去掉四个斜杠&#xff0c;简化成32位 select replace(gen_random_uuid()::text, -, ); 官网介绍…

《前端面试题》- CSS - CSS选择器的优先级

行内样式1000 d选择器100 属性选择器、class或者伪类10 元素选择器&#xff0c;或者伪元素1 通配符0 参考网址&#xff1a;https://blog.csdn.net/jbj6568839z/article/details/113888600https://www.cnblogs.com/RenshuozZ/p/10327285.htmlhttps://www.cnblogs.com/zxjwlh/p/6…

搭建Grafana+Prometheus监控Spring Boot应用

Spring项目改造 maven依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId> </dependency><dependency><groupId>io.micrometer</groupId><artif…

​如何使用 ArcGIS Pro 制作带贴图建筑

对于用GIS软件制作三维建筑&#xff0c;很多时候都是制作的建筑体块&#xff0c;这里为大家介绍一下怎么使用 ArcGIS Pro 制作带贴图的建筑&#xff0c;希望能对你有所帮助。 数据来源 教程所使用的数据是从水经微图中下载的建筑数据&#xff0c;除了建筑数据&#xff0c;常见…

最简洁的Docker环境配置

Docker环境配置 Docker 是一个开源的应用容器引擎&#xff0c;让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中&#xff0c;然后发布到任何流行的 Mac、Linux或Windows操作系统的机器上&#xff0c;也可以实现虚拟化。容器是完全使用沙箱机制&#xff0c;相互之间不…

AI大模型探索之路-应用篇2:Langchain框架ModelIO模块—数据交互的秘密武器

目录 前言 一、概述​​​​​​​ 二、Model 三、Prompt 五、Output Parsers 总结 前言 随着人工智能技术的不断进步&#xff0c;大模型的应用场景越来越广泛。LangChain框架作为一个创新的解决方案&#xff0c;专为处理大型语言模型的输入输出而设计。其中&#xff0c;…

redis主从复制详解

redis主从复制(replica) 1、是什么&#xff1f; 目录 redis主从复制(replica) 1、是什么&#xff1f; 2、能干嘛&#xff1f; 3、怎么玩&#xff1f; 4、案例演示 前置操作 &#x1f357;一主二仆 &#x1f355;薪火相传 &#x1f32d;反客为主 5、复制的原理和工作…

Flutter仿Boss-6.底部tab切换

效果 实现 图片资源采用boss包中的动画webp资源。Flutter采用Image加载webp动画。 遇到的问题 问题&#xff1a;Flutter加载webp再次加载无法再次播放动画问题 看如下代码&#xff1a; Image.asset(assets/images/xxx.webp,width: 40.w,height: 30.w, )运行的效果&#xf…

Vue3 + Vite 构建组件库发布到 npm

你有构建完组件库后&#xff0c;因为不知道如何发布到 npm 的烦恼吗&#xff1f;本教程手把手教你用 Vite 构建组件库发布到 npm 搭建项目 这里我们使用 Vite 初始化项目&#xff0c;执行命令&#xff1a; pnpm create vite my-vue-app --template vue这里以我的项目 vue3-xm…

GPT提示词分享 —— 中医

&#x1f449; 中医诊断涉及因素较多&#xff0c;治疗方案仅供参考&#xff0c;具体的方子需由医生提供。AI建议不能替代专业医疗意见&#xff0c;如果症状严重或持续&#xff0c;建议咨询专业医生。 我希望你能扮演一位既是老中医同时又是一个营养学专家&#xff0c;我讲描述…

Linux部署FTP服务器

文章目录 什么是FTP协议&#xff1f;Linux上部署FTP服务器安装FTP服务启动FTP服务编辑/etc/vsftpd.conf重新启动服务测试FTP服务 什么是FTP协议&#xff1f; FTP协议是一种基于TCP的文件传输协议&#xff0c;能够实现高效的文件上传和下载功能&#xff0c;最重要的是它能够使用…

LeetCode-322. 零钱兑换【广度优先搜索 数组 动态规划】

LeetCode-322. 零钱兑换【广度优先搜索 数组 动态规划】 题目描述&#xff1a;解题思路一&#xff1a;Python动态规划五部曲&#xff1a;定推初遍举【先遍历物品 后遍历背包】解题思路二&#xff1a;Python动态规划五部曲&#xff1a;定推初遍举【先遍历背包 后遍历物品】解题思…

组装机械狗电子玩具方案

这款机械狗玩具电子方案结合了现代电子技术和人工智能元素&#xff0c;旨在为用户提供一个高科技、互动性强的娱乐体验。通过不断的软件更新和硬件迭代&#xff0c;机械狗的功能将持续扩展。 一、功能特点&#xff1a; 1、自动巡游&#xff1a;机械狗能够自主在房间内巡游&am…

一文详解手机IP地址如何改变

在互联网时代&#xff0c;手机的IP地址扮演着至关重要的角色。它不仅是手机在网络中的标识&#xff0c;还关系到手机的网络连接、隐私保护以及访问权限等方面。然而&#xff0c;在某些情况下&#xff0c;我们可能需要改变手机的IP地址&#xff0c;以满足特定的需求或解决网络问…

OLAP在线实时 数据分析平台

随着业务的增长&#xff0c;精细化运营的提出&#xff0c;产品对数据部门提出了更高的要求&#xff0c;包括需要对实时数据进行查询分析&#xff0c;快速调整运营策略&#xff1b;对小部分人群做 AB 实验&#xff0c;验证新功能的有效性&#xff1b;减少数据查询时间&#xff0…

逆向案例十七(1)——webpack加如果之前发送公钥如何定位参数,基于中国五矿

网址链接&#xff1a;中国五矿集团有限公司采购电子商务平台 定位到数据包&#xff0c;载荷中param是一个加密参数。 每一个数据包前都有一个public返回公钥。 点击查看返回的数据 如何定位参数加密位置&#xff1f; 复制公钥包url的后面&#xff0c;进行搜索 &#xff0c;查…

nodejs fs http express express-session jwt mysql mongoose

文件fs模块 读取文件内容 fs.readFile(./file/fs-01.txt, utf8, (err, data) > {if (err) {console.error(err)return}console.log(data) })写入内容到文件 const fs require(fs);const filePath "./file/output.txt";fs.writeFile(filePath, "Hello Wor…