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[]=226
            return 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 debug
    return 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-upload
  style="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);
  }

},

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

相机模型浅析

相机模型 文章目录 相机模型四个坐标系针孔相机模型世界坐标系到相机坐标系相机坐标系到图像坐标系图像坐标到像素坐标 四个坐标系 ①世界坐标系&#xff1a;是客观三维世界的绝对坐标系&#xff0c;也称客观坐标系。因为数码相机安放在三维空间中&#xff0c;我们需要世界坐标…

主流排序简单集合

排序算法集合 选择排序 图解&#xff1a;以此类推直至 /*选择排序*/ void select_sort(vector<int>& nums) {/*选取一个基准元素逐个与后面的比较*/for (int i 0; i < nums.size() - 1-1; i) {int min i;/*定义随之变化的基准元素*/for (int j i 1; j <…

华为 2024 届校园招聘-硬件通⽤/单板开发——第一套(部分题目分享,完整版带答案,共十套)

华为 2024 届校园招聘-硬件通⽤/单板开发——第一套 部分题目分享&#xff0c;完整版带答案(有答案和解析&#xff0c;答案非官方&#xff0c;未仔细校正&#xff0c;仅供参考&#xff09;&#xff08;共十套&#xff09;获取&#xff08;WX:didadidadidida313&#xff0c;加我…

GEE:研究区(Polygon)样式设置

作者:CSDN @ _养乐多_ 本文将介绍在 Google Earth Engine (GEE)平台上为 polygon (面)数据设置样式的方法和代码,polygon 可以设置成任何颜色,以增加可视化效果更好理解数据分布。 结果如下图所示, 文章目录 一、统一样式1.1 示例代码1.2 示例代码链接二、根据区域名…

基于SpringBoot2.x、SpringCloud和SpringCloudAlibaba并采用前后端分离的企业级微服务多租户系统架构

简介 基于SpringBoot2.x、SpringCloud和SpringCloudAlibaba并采用前后端分离的企业级微服务多租户系统架构。并引入组件化的思想实现高内聚低耦合并且高度可配置化&#xff0c;适合学习和企业中使用。 真正实现了基于RBAC、jwt和oauth2的无状态统一权限认证的解决方案&#x…

element UI table合并单元格方法

废话不多讲&#xff0c;直接上代码&#xff0c;希望能帮到需要的朋友 // 合并单元格function spanMethod({ row, column, rowIndex, columnIndex }) {//定义需要合并的列字段&#xff0c;有哪些列需要合并&#xff0c;就自定义添加字段即可const fields [declareRegion] // …

hive-3.1.2分布式搭建与hive的三种交互方式

hive-3.1.2分布式搭建&#xff1a; 一、上传解压配置环境变量 在官网或者镜像站下载驱动包 华为云镜像站地址&#xff1a; hive&#xff1a;Index of apache-local/hive/hive-3.1.2 mysql驱动包&#xff1a;Index of mysql-local/Downloads/Connector-J # 1、解压 tar -zx…

采用Flink CDC操作SQL Server数据库获取增量变更数据

采用Flink CDC操作SQL Server数据库获取增量变更数据 Flink CDC 1.12版本引入了对SQL Server的支持&#xff0c;包括SqlServerCatalog和SqlServerTable。在SqlServerCatalog中&#xff0c;你可以根据表名获取对应的字段和字段类型。 SQL Server 2008 开始支持变更数据捕获 (C…

李廉洋:4.10黄金原油走势最新分析及策略。

美联储博斯蒂克重申了他对今年降息一次的预期&#xff0c;但他补充说&#xff0c;如果经济形势发生变化&#xff0c;他对推迟降息或进一步降息持开放态度。博斯蒂克强调了美国经济和劳动力市场的持续强劲&#xff0c;但表示就业市场的疲软迹象将促使他考虑比目前预期的更早和更…

GFS部署实验

目录 1、部署环境 ​编辑 2、更改节点名称 3、准备环境 4、磁盘分区&#xff0c;并挂载 5. 做主机映射--/etc/hosts/ 6. 复制脚本文件 7. 执行脚本完成分区 8. 安装客户端软件 1. 安装解压源包 2. 创建gfs 3. 安装 gfs 4. 开启服务 9、 添加节点到存储信任池中 1…

SVM向量支持机

1.通俗理解 svm&#xff1a;support vector machine目标&#xff1a;利用超平面将两类数据分割开来&#xff0c;这个超平面就是我们要设计的对象 如何设计&#xff1f;我们设计之后会有间隔&#xff0c;间隔越大分类效果就越好&#xff1b;距离决策边界最近的点我们成为支持向…

40.Python从入门到精通—Python3 JSON 数据解析 Python3 日期和时间 什么是时间元组? 获取当前时间 获取格式化的时间

40.Python从入门到精通—Python3 JSON 数据解析 Python3 日期和时间 什么是时间元组&#xff1f; 获取当前时间 获取格式化的时间 Python3 JSON 数据解析Python3 日期和时间什么是时间元组&#xff1f;获取当前时间获取格式化的时间 Python3 JSON 数据解析 Python3 中可以使用…

使用MongoDB 构建AI:轻松应对从预测式AI到生成式AI

毫无疑问&#xff0c;如今从生成式AI (GenAI )中获益最大的&#xff0c;是那些早已运用预测式AI (Predictive AI )的组织。 2023年6月&#xff0c;麦肯锡在2023年6月发布的《生成式人工智能的经济潜力》研究中也得出了与此相同的结论。 原因主要有以下几点&#xff1a; 内部文…

顺序表(C语言实现)

什么是顺序表 顺序表和数组的区别 顺序表本质就是数组 结构体初阶进阶 系统化的学习-CSDN博客 简单解释一下&#xff0c;就像大家去吃饭&#xff0c;然后左边是苍蝇馆子&#xff0c;右边是修饰过的苍蝇馆子&#xff0c;但是那个好看的苍蝇馆子一看&#xff0c;这不行啊&a…

Harmony鸿蒙南向驱动开发-MIPI CSI

CSI&#xff08;Camera Serial Interface&#xff09;是由MIPI联盟下Camera工作组指定的接口标准。CSI-2是MIPI CSI第二版&#xff0c;主要由应用层、协议层、物理层组成&#xff0c;最大支持4通道数据传输、单线传输速度高达1Gb/s。 物理层支持HS&#xff08;High Speed&…

kettle经验篇:取出一个字符串中的两个数值

项目场景 在一个数据清洗、同步的需求中&#xff1b;有一个要求是判断两个数值是否在正常范围内&#xff0c;并根据判断结果给出异常标记。但这两个数值是以XML的格式存储在Oracle的CLOB字段中&#xff0c;且在同一个XML节点中。该节点的内容如下: "OD: 17.4 mmHg O…

2024Peak码支付系统网站源码

系统简介 Peak码支付-是专为个人站长打造的聚合免签系统&#xff0c;拥有卓越的性能和丰富的功能。用全新轻量化的界面UI&#xff0c;让您可以更加方便快捷地解决知识付费和运营赞助的难题。同时&#xff0c;它基于高性能SpeedPHPLayuiPearAdmin架构&#xff0c;提供实时监控和…

https的配置和使用(以腾讯云为例)

1、注册域名 2、获取证书 3、下载证书 下载下来的证书所有格式 4、在服务器上下载nginx并配置 nginx的配置文件 如下 server {listen 80;listen 443 ssl;server_name delegate.letspiu.net.cn;ssl on; #开启ssl#指定证书位置ssl_certificate /etc/ss…

低代码ARM计算机在IIoT中的采集控制生产面板

工业4.0的大潮下工业物联网&#xff08;IIoT&#xff09;已成为推动制造业转型升级的重要动力。其中&#xff0c;低代码ARM嵌入式计算机凭借其出色的性能、灵活的配置以及高度集成化的特点&#xff0c;在工业设备远程监控、维护与诊断方面发挥着关键作用。 一、远程监控与维护 …

【配电网故障定位】基于二进制蝗虫优化算法的配电网故障定位 12节点配电系统故障定位【Matlab代码#75】

文章目录 【获取资源请见文章第5节&#xff1a;资源获取】1. 配电网故障定位2. 二进制蝗虫优化算法3. 部分代码展示4. 仿真结果展示5. 资源获取 【获取资源请见文章第5节&#xff1a;资源获取】 1. 配电网故障定位 配电系统故障定位&#xff0c;即在配电网络发生故障的时候&am…