使用Excel导入和导出数据

功能技术:SpringBoot,vue3(restful)

前端代码实现

首先在前端写一个上传和导出功能。

html 复制代码
<template>
     <!-- 文件上传 -->
     <el-upload class="upload-demo" drag action="" :on-change="onChange" :auto-upload="false">
          <el-icon class="el-icon--upload"><upload-filled /></el-icon>
          <div class="el-upload__text">
               Drop file here or <em>click to upload</em>
          </div>
     </el-upload>
     <!-- 文件导出 -->
     <a target="_blank" type="success" href="/api/upload/write">导出Excle</a>

</template>

<script lang="ts" setup>
import { uploadApi } from "@/api/index";
import { ElMessage } from "element-plus";

//定义文件上传的函数
const onChange = (file: any, _uploadFiles: any) => {
     let reader = new FileReader();
     reader.readAsDataURL(file.raw);
     reader.onload = (f) => {
          callUploadApi(file.name, f.target?.result);
     };
};
//文件上传的函数
const callUploadApi = (name: any, base64: any) => {
     uploadApi.uploadExcel.call({ name, base64 }).then((res: any) => {
          ElMessage.success("上传成功");
     });
};

</script>

请求配置:uploadApi.ts

java 复制代码
import http from "@/http/index";
export default {
  uploadExcel: {
    name: "上传文件",
    url: "/api/upload/excel",
    call: async function name(params: any) {
      return await http.post(this.url, params);
    },
  },
};

index.ts

java 复制代码
import uploadApi from "@/api/uploadApi";
export {uploadApi};

数据库文件

sql 复制代码
CREATE TABLE `person` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL COMMENT '姓名',
  `age` int(11) DEFAULT NULL COMMENT '年龄',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

后端代码实现

导入操作excel的依赖poi

XML 复制代码
<!--poi-->
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>5.0.0</version>
</dependency>

准备工作:1、一个与你上传数据相对于的实体类;

2、定义一个上传信息对象;

实体类Person:为了方便演示我就定义两个字段,以供参考:

java 复制代码
@Data
public class Person {
    private String name;
    private Integer age;
}

上传信息对象UploadInfo :

java 复制代码
@Data
public class UploadInfo {
    private String name;
    private String base64;
}

Controller层代码:

java 复制代码
@RestController
@RequestMapping("/api/upload")
public class UploadExcel {
 
    @Autowired
    private SqlSessionFactory sqlSessionFactory;
    @Autowired
    private PersonDao personDao;
    @Autowired
    private UploadService uploadService;
 
 
    /**
     * 导入excle
     * @param uploadInfo
     * @return
     * @throws Exception
     */
    @PostMapping("/excel")
    public String upload1(@RequestBody UploadInfo uploadInfo) throws Exception {
        String name = uploadInfo.getName();
        String base64 = uploadInfo.getBase64();
        String[] strArray = StrUtil.splitToArray(base64, "base64,");
        byte[] bytes = Base64.decode(strArray[1]);

        //用于创建一个基于字节数组的输入流。它允许你从一个字节数组中读取数据。
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
        // 使用Hutool读取Excel文件
        ExcelReader reader = ExcelUtil.getReader(byteArrayInputStream);
        //将读取到的 reader 转化为 List<Man>集合
        List<Person> persons = reader.readAll(Person.class);

        //StopWatch类是 Hutool 工具库中的类,用于测量代码执行时间
        StopWatch stopWatch = new StopWatch();
        //读取数据的结束时间同时也是写入数据库的开始时间
        stopWatch.start();

        //sqlSessionFactory是通过ioc容器注入的  设置其SqlSession的执行器格式ExecutorType.SIMPLE(默认)
        SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
        PersonDao mapper = sqlSession.getMapper(PersonDao.class);
        //循环将List<Man>中的数据插入数据库 方法一
        //for (Person person : persons) {
        //    PoItemMapper.xml.insert(person);
        //}
        //方法二:
        mapper.insertBatch(persons);
        sqlSession.commit();
        stopWatch.stop();
        sqlSession.close();
        System.out.println("插入数据库最终的结果为:" + stopWatch.getTotalTimeSeconds());

        return "ok";
    }

    /**
     * 导出Excel
     * @param response
     * @throws IOException
     */
    @GetMapping("/write")
    public void exportExcel(HttpServletResponse response) throws IOException {
        // 创建Excel写入器   参数 true 表示追加数据,即在已有的 Excel 文件上追加新数据。如果设为 false,则会覆盖已有的数据。
        List<Person> person = personDao.selectAll();
        // 创建ExcelWriter对象
        ExcelWriter writer = ExcelUtil.getWriter(true);
        int i = 0;
        while (true) {
            List<Person> list = person.stream().skip(i * 100000).limit(100000).parallel().collect(Collectors.toList());
            if (list.isEmpty()) {
                break;
            }
            writer.setSheet("person" + i);
            // 写入表头
            writer.addHeaderAlias("id", "Id");
            writer.addHeaderAlias("name", "姓名");
            writer.addHeaderAlias("age", "年龄");
            // 写入当前批次的数据
            writer.write(list, true);
            i++;
        }
        //response为HttpServletResponse对象   设置响应的内容类型为Excel文件
        response.setContentType("application/xlsx;charset=utf-8");
        //test.xls是弹出下载对话框的文件名,不能为中文,中文请自行编码
        //设置响应头,告诉浏览器以附件形式下载文件,文件名为test.xlsx。这样设置可以让浏览器弹出文件下载对话框。
        response.setHeader("Content-Disposition", "attachment;filename="+"test.xlsx");
        //获取响应输出流,它是用于将响应的数据发送给客户端的流。
        ServletOutputStream out = response.getOutputStream();
        //将Excel数据写入输出流。第二个参数为true表示追加写入,即将数据追加到已有的Excel文件中。
        writer.flush(out, true);
        writer.close();
        //关闭输出流
        out.close();
    }
}

dao层代码PersonDao :

java 复制代码
@Mapper
public interface PersonDao {
    
    void insert(Person person);
 
    void insertBatch(List<Person> persons);
 
    List<Person> selectAll();
 
}

PersonMappr.xml:

java 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.by.dao.PersonMapper">
    <!--新增数据-->
    <insert id="insert">
        insert into person(name,age)
        values (#{name},#{age})
    </insert>
    <!-- 批量新增数据 -->
    <insert id="insertBatch" >
        insert into person(name,age)
        values
        <foreach collection="persons" item="entity" separator=",">
            (#{entity.name},#{entity.age})
        </foreach>
    </insert>
    <select id="selectAll" resultType="com.by.upload.Person">
        select * from person
    </select>
</mapper>
相关推荐
yinuo2 小时前
前端跨页面通讯终极指南⑥:SharedWorker 用法全解析
前端
CoderYanger6 小时前
C.滑动窗口-求子数组个数-越长越合法——2799. 统计完全子数组的数目
java·c语言·开发语言·数据结构·算法·leetcode·职场和发展
C++业余爱好者6 小时前
Java 提供了8种基本数据类型及封装类型介绍
java·开发语言·python
想用offer打牌6 小时前
RocketMQ如何防止消息丢失?
java·后端·架构·开源·rocketmq
皮卡龙6 小时前
Java常用的JSON
java·开发语言·spring boot·json
PineappleCoder6 小时前
还在重复下载资源?HTTP 缓存让二次访问 “零请求”,用户体验翻倍
前端·性能优化
拉不动的猪6 小时前
webpack编译中为什么不建议load替换ast中节点删除consolg.log
前端·javascript·webpack
李姆斯6 小时前
Agent时代下,ToB前端的UI和交互会往哪走?
前端·agent·交互设计
利刃大大7 小时前
【JavaSE】十三、枚举类Enum && Lambda表达式 && 列表排序常见写法
java·开发语言·枚举·lambda·排序
float_六七7 小时前
Java反射:万能遥控器拆解编程
java·开发语言