如何导入导出Excel表格(vue2+SpringBoot+Element+easyexcel)
目录
前端
1、编写模板
<template>
<div>
<el-upload ref="upload" class="upload-demo" action="http://localhost:8080/api/book/uploadExcel" :limit="1"
:before-upload="beforeUpload" :on-success="handleSuccess" :on-error="uploadError" :file-list="fileList">
<el-button type="primary">导入</el-button>
</el-upload>
<el-button type="success" @click="downloadExcel">导出</el-button>
</div>
</template>
上述代码是一个 Vue 组件的模板部分。这个组件包含了两个按钮:一个用于文件上传,另一个用于文件导出。
<el-upload>
是 Element UI 提供的上传组件,通过设置action
属性指定了文件上传的目标地址。:limit="1"
表示限制只能上传一个文件。:before-upload
、:on-success
和:on-error
是组件提供的事件回调函数,用于处理上传前的验证、上传成功和上传失败的情况。:file-list="fileList"
则是绑定了一个文件列表,用于展示已上传的文件。<el-button>
是 Element UI 提供的按钮组件,通过设置type
属性指定按钮的样式类型。@click
是按钮点击事件的监听器,绑定了名为downloadExcel
的方法。
2、发请求
<script>
export default {
name: 'book',
data() {
return {
fileList: []
}
},
methods: {
//导出
downloadExcel() {
this.$axios({
method: 'get',
url: ' http://localhost:8080/api/book/downloadExcel',
responseType: 'blob'
}).then((res) => {
let filename = decodeURIComponent(res.headers.get('X-Filename'));
const url = window.URL.createObjectURL(new Blob([res.data]))
const link = document.createElement('a')
link.href = url
link.setAttribute('download', filename)
document.body.appendChild(link)
link.click()
})
},
//上传之前调用:校验类型、大小
beforeUpload(file) {
console.log("file.type:" + file.type);
const fileSize = file.size / Math.pow(2, 20);
if (file.type !== 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') {
this.$message.error('只能上传excel文件')
return false;
}
if (fileSize > 10) {
this.$message.error("图片不能超过10MB")
return false;
}
return true;
},
//图片上传成功之后:将上传图片的数据添加到fileList
handleSuccess(response, file, fileList) {
// 根据后端返回的数据修改fileList集合
console.log("图片上传成功之后response:" + JSON.stringify(response));
},
//上传失败的逻辑
uploadError(err, file, fileList) {
this.$message({
message: err.message,
type: "error",
});
},
}
}
</script>
this.$axios
是 Vue 实例中的$axios
对象,用于发送 HTTP 请求。method: 'get'
表示发送 GET 请求。url: 'http://localhost:8080/api/book/downloadExcel'
指定了要下载的 Excel 文件的地址。responseType: 'blob'
表示期望响应的数据类型为 Blob 类型,即二进制数据。
在请求成功后,使用 then
方法处理返回的响应。res
是响应对象,包含了服务器返回的数据和响应头等信息。
let filename = decodeURIComponent(res.headers.get('X-Filename'))
从响应头中获取文件名,并进行 URL 解码。const url = window.URL.createObjectURL(new Blob([res.data]))
创建一个临时的 URL,用于将二进制数据转换为可下载的文件。const link = document.createElement('a')
创建一个<a>
元素,用于触发文件下载。link.href = url
设置<a>
元素的链接地址为临时 URL。link.setAttribute('download', filename)
设置下载属性,其中filename
是文件名。document.body.appendChild(link)
将<a>
元素添加到文档中。link.click()
触发点击事件,实现文件下载。
后端
相关依赖
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.0.1-jre</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.0.2</version>
</dependency>
1、创建实体类
import java.util.Date;
public class Book {
@ExcelIgnore //设置导出时不导出这个字段
private String bookId;
@ExcelProperty(value="书名",index = 0)//value 属性指定了 Excel 列的标题或名称,index 属性指定了 Excel 列的索引位置
@ColumnWidth(15) // 设置宽度为16个字符
private String bookName;
@ExcelProperty(value="作者",index = 1)
@ColumnWidth(15) // 设置宽度为16个字符
private String author;
@ExcelProperty(value="价格",index = 2)
private double price;
@ExcelProperty(value="图书编号",index = 3)
@ColumnWidth(25) // 设置宽度为16个字符
private String isbn;
@ExcelProperty(value="出版社",index = 4)
@ColumnWidth(15) // 设置宽度为16个字符
private String publisher;
@ExcelProperty(value="发行日期",index = 5)
@ColumnWidth(20) // 设置宽度为16个字符
// @DateTimeFormat("yyyy年MM月dd日HH时mm分ss秒")
@DateTimeFormat("yyyy-MM-dd HH:mm:ss")
private Date releaseTime;
@ExcelIgnore
private String status;
public Book() {
}
public static void main(String[] args) {
Book book = new Book();
//book 反射
Class<? extends Book> aClass = book.getClass();
System.out.println(aClass.getName());
}
public Book(String bookId, String bookName, String author, double price, String isbn, String publisher, Date releaseTime, String status) {
this.bookId = bookId;
this.bookName = bookName;
this.author = author;
this.price = price;
this.isbn = isbn;
this.publisher = publisher;
this.releaseTime = releaseTime;
this.status = status;
}
public String getBookId() {
return bookId;
}
public void setBookId(String bookId) {
this.bookId = bookId;
}
public String getBookName() {
return bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public String getIsbn() {
return isbn;
}
public void setIsbn(String isbn) {
this.isbn = isbn;
}
public String getPublisher() {
return publisher;
}
public void setPublisher(String publisher) {
this.publisher = publisher;
}
public Date getReleaseTime() {
return releaseTime;
}
public void setReleaseTime(Date releaseTime) {
this.releaseTime = releaseTime;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
}
2、编写控制类
@RestController
@RequestMapping("/book")
public class BookController {
@Autowired
BookService bookService;
@PostMapping("/uploadExcel")
public Result uploadExcel(@RequestPart MultipartFile file) {
return bookService.uploadExcel(file);
}
@GetMapping("/downloadExcel")
public void downloadExcel(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws IOException {
bookService.downloadExcel(httpServletResponse);
}
}
@RestController
注解表示这是一个 RESTful 服务的控制器类,用于处理 HTTP 请求并返回 JSON 或 XML 等数据。@RequestMapping("/book")
注解表示该控制器中所有处理 "/book" 路径下的请求。
控制器中包含两个方法:
-
uploadExcel
方法处理 POST 请求,用于接收上传的 Excel 文件,并调用BookService
的uploadExcel
方法进行处理。@RequestPart MultipartFile file
表示从请求中接收名为 "file" 的文件部分,并将其作为 MultipartFile 对象注入到方法参数中。上传成功后,返回处理结果(Result 对象)。 -
downloadExcel
方法处理 GET 请求,用于下载 Excel 文件,并调用BookService
的downloadExcel
方法。通过传入HttpServletResponse
对象来设置响应,实现文件下载功能。 -
HttpServletRequest
和HttpServletResponse
。这两个参数分别表示 HTTP 请求和响应。在方法内部,调用了
bookService
的downloadExcel
方法,并传入httpServletResponse
。这意味着在bookService
的downloadExcel
方法中会对 HttpServletResponse 进行操作,以便向客户端发送 Excel 文件。在
bookService
的downloadExcel
方法中,通常会进行以下操作:
- 设置响应的内容类型,告诉客户端响应的数据类型是 Excel 文件。
- 设置响应的头部信息,包括文件名、内容长度等。
- 将 Excel 文件的内容写入到响应的输出流中,使客户端可以下载该文件。
3、service层
接口
public interface BookService {
Result uploadExcel(MultipartFile file);
void downloadExcel(HttpServletResponse httpServletResponse) throws IOException;
}
接口实现
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
@Service
public class BookServiceImpl implements BookService {
/**
* 每隔1000条存储数据库,然后清理list ,方便内存回收
*/
//TODO 定义变量
private static final int BATCH_COUNT = 1000;
@Autowired
BookMapper bookMapper;
@Override
public Result uploadExcel(MultipartFile file) {
try {
// 1、获取输入流,这里需要自行实现获取输入流的逻辑
InputStream inputStream = file.getInputStream();
//2、解析输入流数据,并添加到集合
List<Book> list = EasyExcelUtil.read(inputStream, Book.class);
//3、对集合进行分批次
List<List<Book>> partition = Lists.partition(list, BATCH_COUNT);
//4、保存到数据库
for (List<Book> bookList : partition) {
bookMapper.batchInsertBook(bookList);
}
} catch (Exception e) {
// 处理异常
e.printStackTrace();
return Result.failed("导入失败");
}
return Result.succeed("导入成功");
}
@Override
public void downloadExcel(HttpServletResponse httpServletResponse) throws IOException {
//1、查询数据库数据
List<Book> list =bookMapper.selectAllBook();
//导出
EasyExcelUtil.download(httpServletResponse,list,Book.class, "喜欢看得书籍","书籍");
}
}
- 在
uploadExcel
方法中,首先通过file.getInputStream()
获取上传文件的输入流。然后使用EasyExcelUtil.read
方法将输入流中的数据解析成Book
对象的列表。接着,使用Lists.partition
方法将列表分割成小的批量列表,每个批量包含多个Book
对象。最后,遍历分割后的批量列表,调用bookMapper.batchInsertBook
方法将批量数据插入到数据库中。 - 在
downloadExcel
方法中,首先通过bookMapper.selectAllBook()
从数据库中获取所有的书籍数据。然后使用EasyExcelUtil.download
方法将获取到的书籍列表以 Excel 文件的形式下载到客户端。其中,Book.class
是指定数据对象的类,"喜欢看得书籍" 是指定生成的 Excel 文件名称,"书籍" 是指定 Excel 文件的 sheet 名称。
这样,通过调用 BookServiceImpl
类中的方法,可以实现上传和下载 Excel 文件的功能。
4、Mapper层
接口mapper
public interface BookMapper {
void batchInsertBook(List<Book> list);
List<Book> selectAllBook();
}
mapper对应的xml
<?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.example.goods_admin.mapper.BookMapper">
<!-- 结果映射:数据库字段与实体类字段的映射关系-->
<resultMap id="BaseResultMap" type="com.example.goods_admin.entity.Book">
<id column="bookId" jdbcType="INTEGER" property="bookId" />
<result column="bookName" jdbcType="VARCHAR" property="bookName" />
<result column="author" jdbcType="VARCHAR" property="author" />
<result column="price" jdbcType="DOUBLE" property="price" />
<result column="isbn" jdbcType="VARCHAR" property="isbn" />
<result column="publisher" jdbcType="INTEGER" property="publisher" />
<result column="releaseTime" jdbcType="VARCHAR" property="releaseTime" />
<result column="status" jdbcType="VARCHAR" property="status" />
</resultMap>
<insert id="batchInsertBook">
insert into book(bookName,author,price,isbn,publisher,releaseTime) values
<foreach collection="list" item="item" separator=",">
(#{item.bookName},#{item.author},#{item.price},#{item.isbn},#{item.publisher},#{item.releaseTime})
</foreach>
</insert>
<select id="selectAllBook" resultType="com.example.goods_admin.entity.Book">
select * from book where status='1'
</select>
</mapper>
5、工具类
package com.example.goods_admin.utils;
import com.alibaba.excel.EasyExcel;
import com.example.goods_admin.listener.DataListener;
import org.springframework.http.MediaType;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.List;
public class EasyExcelUtil {
public static <T> List<T> read(String filePath) {
File f = new File(filePath);
try (FileInputStream fis = new FileInputStream(f)) {
return read(String.valueOf(fis));
} catch (FileNotFoundException e) {
} catch (IOException e) {
}
return null;
}
public static <T> List<T> read(InputStream inputStream, final Class<T> clazz) {
if (inputStream == null) {
}
// 有个很重要的点 DataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
DataListener<T> listener = new DataListener<>();
// 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
EasyExcel.read(inputStream, clazz, listener).sheet().doRead();
return listener.getRows();
}
public static void write(String outFile, List<?> list) {
Class<?> clazz = list.get(0).getClass();
// 新版本会自动关闭流,不需要自己操作
EasyExcel.write(outFile, clazz).sheet().doWrite(list);
}
public static void write(String outFile, List<?> list, String sheetName) {
Class<?> clazz = list.get(0).getClass();
// 新版本会自动关闭流,不需要自己操作
EasyExcel.write(outFile, clazz).sheet(sheetName).doWrite(list);
}
public static void write(OutputStream outputStream, List<?> list, String sheetName) {
Class<?> clazz = list.get(0).getClass();
// 新版本会自动关闭流,不需要自己操作
// sheetName为sheet的名字,默认写第一个sheet
EasyExcel.write(outputStream, clazz).sheet(sheetName).doWrite(list);
}
/**
* 文件下载(失败了会返回一个有部分数据的Excel),用于直接把excel返回到浏览器下载
*/
public static <T> void download(HttpServletResponse response, List<?> list, Class<T> tClass, String fileName, String sheetName) throws IOException {
//如果 fileName 中包含空格字符,那么这些字符会被编码成 %20,因为在 URL 中空格字符必须被转义成 %20 才能正确传输
fileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
//必须:设置文件响应格式为二进制二进制流数据类型
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
//必须:设置 HTTP 响应的字符编码,以便客户端能够正确地解码和显示接收到的文本数据
response.setCharacterEncoding("utf-8");
//必须:通过设置 Content-Disposition 头部,告诉客户端如何处理接收到的响应内容,以及指定附件的文件名
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
EasyExcel.write(response.getOutputStream(), tClass).sheet(sheetName).doWrite(list);
}
}
6、sql脚本
/*
Navicat Premium Data Transfer
Source Server : database
Source Server Type : MySQL
Source Server Version : 80029
Source Host : localhost:3306
Source Schema : goods_admin
Target Server Type : MySQL
Target Server Version : 80029
File Encoding : 65001
Date: 28/01/2024 22:25:45
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for book
-- ----------------------------
DROP TABLE IF EXISTS `book`;
CREATE TABLE `book` (
`bookId` int NOT NULL AUTO_INCREMENT COMMENT '主键id',
`bookName` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '书名',
`author` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '作者',
`price` double(10, 2) NULL DEFAULT NULL COMMENT '价格',
`isbn` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '图书编号',
`publisher` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '出版社',
`releaseTime` datetime(0) NULL DEFAULT NULL COMMENT '发行日期',
`status` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '1' COMMENT '状态',
PRIMARY KEY (`bookId`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 25 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
SET FOREIGN_KEY_CHECKS = 1;
更多推荐
所有评论(0)