Easy Excel从入门到精通!!!
目录
1.文件导入
1.1基本方式读取excel文件内容
1.2注解+模型映射器读取excel
1.3多行表头读取
1.4文件上传读取
2.文件导出
2.1基本方式导出
2.2模型映射导出
2.3设置行高、列宽等内容
2.4合并单元格
2.5导出设置超链接、批注、公式
2.6模板填充对象导出
2.7模板填充对象列表导出
2.8模板组合填充
3.文件下载
EasyExcel是一个基于Java的、快速、简洁、解决大文件内存溢出的Excel处理工具。
他能让你在不用考虑性能、内存的等因素的情况下,快速完成Excel的读、写等功能
1.文件导入
1.1基本方式读取excel文件内容
read为读取,sheet就是指定excel文件中第几个sheet页,doReadnSync为结尾方法
//指定位置读取excel内容
@Test
public void test01(){
File file = new File("C:\\Users\\Lenovo\\Desktop\\excel\\user-list.xlsx");
List<Object> objects = EasyExcel.read(file).sheet(0).doReadSync();
for (Object object : objects) {
log.info("读取内容为{}",object);
}
}
//输入流读取
@Test
public void test02(){
InputStream inputStream = EazyExcelTest.class.getClassLoader().getResourceAsStream("user-list.xlsx");
List<Map<Integer, Object>> list = EasyExcel.read(inputStream).sheet(0).doReadSync();
for (Map<Integer, Object> item : list) {
log.info("昵称: {}, 性别: {}, 生日: {}, 邮箱: {}, 积分: {}", item.get(0), item.get(1), item.get(2), item.get(3), item.get(4));
}
}
1.2注解+模型映射器读取excel
在上面中读取的excel返回的其实是个Map其中key为下标value为单元格数据,但是如果通过map.get()方式进行获取就太麻烦了,所以我们可以定义一个类让他去和excel文件数据进行映射这样在去操作对象就方便多了
表格为
实体类为
其中的注解起到的作用就是进行与excel表格字段进行映射下面我一一来说
@ExcelProperty(value = " "),这个注解是最基本的通过它与表格字段进行映射
@DateTimeFormat(value = "年月日时分秒"),这个注解负责和表格的日期字段进行映射
@NumberFormat(value = " ")这个注解负责数字转换,用String
去接收excel数字格式的数据会调用这个注解,如果想什么结尾就在结尾加上例如%
@Data
public class UserInfoModel {
/**
* 昵称。
*/
@ExcelProperty(value = "昵称")
private String userName;
/**
* 性别。
*/
@ExcelProperty(value = "性别",converter = UserInfoGenderConverter.class)
private Integer userGender;
/**
* 生日。
*/
@ExcelProperty(value = "生日")
@DateTimeFormat(value = "yyyy-MM-dd")
private String userBirth;
/**
* 邮箱。
*/
@ExcelProperty(value = "邮箱")
private String userEmail;
/**
* 积分。
*/
@ExcelProperty(value = "积分")
private Integer userScore;
/**
* 排名。
*/
@ExcelProperty(value = "排名")
@NumberFormat(value = "#.##%")
private String userRank;
}
我们看到在注解@ExcelProperty(value =" ") 后面有个convert他的作用就是因为字段男女是单一的在excel中,我们想在程序中用数字表示就可以自定义一个模型映射器进行转换,代码如下,实现converter指定类型然后做判断返回
/**
* 用户信息,性别,转换器。
*/
public class UserInfoGenderConverter implements Converter<Integer> {
public Integer convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
String valuee = cellData.getStringValue();
switch (valuee) {
case "男":
return 1;
case "女":
return 2;
default:
return 0;
}
}
}
读取代码
@Test
public void test3() {
File file = new File("C:\\Users\\Lenovo\\Desktop\\excel\\user-list.xlsx");
List<UserInfoModel> list = EasyExcel.read(file).sheet(0).head(UserInfoModel.class).doReadSync();
for (UserInfoModel item : list) {
log.info("昵称: {}, 性别: {}, 生日: {}, 邮箱: {}, 积分: {},排名{}", item.getUserName(), item.getUserGender(), item.getUserBirth(), item.getUserEmail(), item.getUserScore(),item.getUserRank());
}
}
1.3多行表头读取
开发中有可能用户上传的表格是从第几行之后才是正式的数据,而我们在代码中默认的就是从第一行进行读取,遇到这种情况我们可以指定从第几行读取,通过headRowNumber进行实现
实例
代码
@Test
public void test4() {
File file = new File("C:\\Users\\Lenovo\\Desktop\\excel\\user-list2.xlsx");
List<UserInfoModel> list = EasyExcel.read(file).headRowNumber(6).sheet(0).head(UserInfoModel.class).doReadSync();
for (UserInfoModel item : list) {
log.info("昵称: {}, 性别: {}, 生日: {}, 邮箱: {}, 积分: {},排名{}", item.getUserName(), item.getUserGender(), item.getUserBirth(), item.getUserEmail(), item.getUserScore(), item.getUserRank());
}
}
1.4文件上传读取
通过ApiPost上传文件,后台进行读取处理
@RestController
@RequestMapping("/home")
public class HomeController {
@PostMapping("/upload")
@SneakyThrows
public List<UserInfoModel> upload(@RequestPart("file") MultipartFile file) {
InputStream inputStream = file.getInputStream();
List<UserInfoModel> list = EasyExcel.read(inputStream)
.head(UserInfoModel.class).headRowNumber(6).sheet(0).doReadSync();
return list;
}
}
2.文件导出
2.1基本方式导出
首先我们需要新建一张表用于导出时指定位置,下面演示导出三种数据方式;write指定要导出位置的excel表,sheet指定sheet名称dowrite指定导出的数据
/**
* 导出路径。
*/
private final String EXPORT_PATH = "C:\\Users\\Lenovo\\Desktop\\excel\\eazyExcel.xlsx";
/**
* 演示:List<List<Object>> 方式导出。
*/
@Test
public void test01(){
List<Object> list1 = Arrays.asList("郭德纲",28,"男");
List<Object> list2 = Arrays.asList("郭麒麟",30,"男");
List<List<Object>> asList = Arrays.asList(list1, list2);
EasyExcel.write(EXPORT_PATH).sheet("export").doWrite(asList);
}
/**
* Map导出
*/
@Test
public void test02(){
Map<Integer,Object> map1 = new HashMap<>();
map1.put(0,"郭德纲");
map1.put(1,28);
map1.put(2,"男");
Map<Integer,Object> map2 = new HashMap<>();
map2.put(0,"郭麒麟");
map2.put(1,60);
map2.put(2,"男");
List<Map<Integer, Object>> asList = Arrays.asList(map1, map2);
EasyExcel.write(EXPORT_PATH).sheet("export1").doWrite(asList);
}
/**
* 对象导出
*/
@Test
@SneakyThrows
public void test03(){
UserInfoModel userInfoModel1 = new UserInfoModel();
userInfoModel1.setUserBirth(DateUtils.parseDate("1997-06-29"));
userInfoModel1.setUserName("郭德纲");
userInfoModel1.setUserGender(28);
UserInfoModel userInfoModel2 = new UserInfoModel();
userInfoModel2.setUserBirth(DateUtils.parseDate("1997-06-29"));
userInfoModel2.setUserName("郭麒麟");
userInfoModel2.setUserGender(28);
OrderInfoModel orderInfoModel = new OrderInfoModel();
orderInfoModel.setOrderTime(DateUtils.parseDate("1987-06-28"));
orderInfoModel.setOrderTitle("订单标题");
orderInfoModel.setOrderPrice(new BigDecimal("10"));
List<Object> list = Arrays.asList(userInfoModel1, userInfoModel2,orderInfoModel);
EasyExcel.write(EXPORT_PATH).sheet("export2").doWrite(list);
}
2.2模型映射导出
在开发中我们通常是根据前端传过来的参数去DB中查询出对应数据封装成对象集合的形式然后导出
模拟获取数据
/**
* 获取用户信息列表。
*
* @return 返回结果。
*/
@SneakyThrows
private List<UserInfoModel> getList() {
UserInfoModel user1 = new UserInfoModel();
user1.setUserName("郭德纲"); // 用户姓名。
user1.setUserGender(1); // 用户性别。
user1.setUserBirth(DateUtils.parseDate("1973-01-18")); // 用户生日。
user1.setUserScore(100); // 用户积分。
user1.setUserReward(BigDecimal.valueOf(123.45)); // 用户佣金。
UserInfoModel user2 = new UserInfoModel();
user2.setUserName("于谦"); // 用户姓名。
user2.setUserGender(2); // 用户性别。
user2.setUserBirth(DateUtils.parseDate("1967-12-06")); // 用户生日。
user2.setUserScore(200); // 用户积分。
user2.setUserReward(BigDecimal.valueOf(234.56)); // 用户佣金。
UserInfoModel user3 = new UserInfoModel();
user3.setUserName("岳云鹏"); // 用户姓名。
user3.setUserGender(0); // 用户性别。
user3.setUserBirth(DateUtils.parseDate("1985-09-17")); // 用户生日。
user3.setUserScore(300); // 用户积分。
user3.setUserReward(BigDecimal.valueOf(345.67)); // 用户佣金。
return Arrays.asList(user1, user2, user3);
}
实体类
在导入时我们会根据excel文件的表头映射成实体类一一对应然后将list集合进行数据操作,同理导出也是一样的我们查询出的数据映射到实体类然后设置表头这样就能导出excel文件了,这里的注解和上面导入一样,其中我们可以在@ExcelProperty注解中通过{ }将字段汇总到一个表头下,@ExclIgnore注解的作用就是排除掉这个字段不让他在表格中出现
/**
* 用户信息,模型。
*/
@Data
public class UserInfoModel implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 用户姓名。
*/
@ExcelProperty(value = {"基本信息","用户姓名"})
private String userName;
/**
* 用户性别。
*/
@ExcelProperty(value = {"基本信息","用户性别"},converter = UserInfoModelConvert.class)
private Integer userGender;
/**
* 用户生日。
*/
@ExcelProperty(value = {"基本信息","用户生日"})
@DateTimeFormat(value = "yyyy年MM月dd日")
private Date userBirth;
/**
* 用户积分。
*/
@ExcelProperty(value = "用户积分")
private Integer userScore;
/**
* 用户佣金。
*/
@ExcelProperty(value = "用户佣金")
@NumberFormat(value = "$#.##")
@ExcelIgnore
private BigDecimal userReward;
}
导出代码
导出excludeColumnFieldNames的意思是排除调那些字段,includeColumnFieldNames是只要那些字段
public static final String EXPORT_FILE = "C:\\Users\\Lenovo\\Desktop\\excel\\eazyExcel.xlsx";
/**
* 测试:模型映射导出。
*/
@Test
@SneakyThrows
public void testExport() {
// 获取:用户信息列表。
List<UserInfoModel> list = this.getList();
// 处理:导出数据。
EasyExcel.write(EXPORT_FILE).head(UserInfoModel.class)
.sheet("sheet01").excludeColumnFieldNames(Arrays.asList("userScore")).doWrite(list);
}
2.3设置行高、列宽等内容
@ContentRowHeight(value = 20) //行高(内容)只能加在类上 @HeadRowHeight(value = 20) //行高 (标题)只能加在类上 @ColumnWidth(value = 20) //列宽 可以加在类上也可以加在字段上
导出代码
其中.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) //自适应表格格式
/**
* 测试:模型映射导出。
*/
@Test
@SneakyThrows
public void testExport() {
// 获取:用户信息列表。
List<UserInfoModel> list = this.getList();
// 处理:导出数据。
EasyExcel.write(EXPORT_FILE)
.sheet("导出数据")
.head(UserInfoModel.class)
.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) //自适应格式
.doWrite(list);
}
实体类
/**
* 用户信息,模型。
*/
@Data
@ContentRowHeight(value = 20) //行高(内容)
@HeadRowHeight(value = 20) //行高 (标题)
public class UserInfoModel implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 用户姓名。
*/
@ExcelProperty(value = {"基本信息", "用户姓名"})
private String userName;
/**
* 用户性别。
*/
@ExcelProperty(value = {"基本信息", "用户性别"})
private Integer userGender;
/**
* 用户生日。
*/
@ExcelProperty(value = {"基本信息", "用户生日"})
@DateTimeFormat(value = "yyyy年MM月dd日")
@ColumnWidth(value = 20)
private Date userBirth;
/**
* 用户积分。
*/
@ExcelProperty(value = {"账户信息", "用户积分"})
private Integer userScore;
/**
* 用户佣金。
*/
@ExcelProperty(value = {"账户信息", "用户佣金"})
@NumberFormat(value = "¥#.##")
private BigDecimal userReward;
}
2.4合并单元格
合并单元格也很常见,共有两种方式
方式1:注解合并
@OnceAbsoluteMerge加在类上指定某个单元格进行合并
@ContentLoopMerge加在某个表头下指定数量进行循环合并
/**
* 用户信息,模型。
*/
@Data
//@OnceAbsoluteMerge(firstRowIndex = 2, lastRowIndex = 3, firstColumnIndex = 0, lastColumnIndex = 0) //单次指定某个单元格合并
//firstRowIndex = 起始位置为0 2的话也就是第三行的位置, lastRowIndex = 3其实位置为0就是firstRowIndex到3的位置进行合并, firstColumnIndex = 0第几列, lastColumnIndex = 0第几列结束
public class UserInfoModel implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 团队名称。
*/
@ExcelProperty(value = "团队名称")
@ContentLoopMerge(eachRow = 2) //循环合并就是自动合并,在团队名称单元格下面自动进行每两个单元格进行合并,但是不智能可能会多出来一行
private String teamName;
方式2:代码合并
.registerWriteHandler(new OnceAbsoluteMergeStrategy(0,1,4,4))//指定单元格进行合并一次 .registerWriteHandler(new LoopMergeStrategy(2,0))//循环合并
@Test
@SneakyThrows
public void test() {
EasyExcel.write(EXPORT_FILE).head(UserInfoModel.class).registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
.registerWriteHandler(new OnceAbsoluteMergeStrategy(0,1,4,4))//指定单元格进行合并一次
.registerWriteHandler(new LoopMergeStrategy(2,0))//循环合并
.sheet("sheet1").doWrite(this::getList);
}
2.5导出设置超链接、批注、公式
一句话概括就是在你要设置的字段上加上原始数据类型WriteCellData<类型>,然后在代码中进行添加就可以了,如下所示;导出公式不常用这里不做演示
模型类
/**
* 用户信息,模型类。
*/
@Data
@ColumnWidth(value = 20)
public class UserInfoModel implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 行号。
*/
@ExcelIgnore
@ExcelProperty(value = "行号")
private Integer rowNumber;
/**
* 用户标识。
*/
@ExcelProperty(value = "用户标识")
private WriteCellData<Long> id;
/**
* 用户昵称。
*/
@ExcelProperty(value = "用户昵称")
private WriteCellData<String> userNickName;
/**
* 用户性别。
*/
@ExcelProperty(value = "用户性别")
private Integer userGender;
/**
* 用户生日。
*/
@ExcelProperty(value = "用户生日")
private Date userBirth;
/**
* 用户年龄。
*/
@ExcelIgnore
@ExcelProperty(value = "用户年龄")
private Integer userAge;
}
导出代码
@Test
public void test() {
List<UserInfoEntity> list = userInfoService.list();
List<UserInfoModel> modelList = list.stream().map(item -> {
UserInfoModel userInfoModel = new UserInfoModel();
//添加批注
CommentData commentData = new CommentData();
commentData.setAuthor("我是作者李佳伟");
commentData.setRichTextStringData(new RichTextStringData("这是批注内容"));
WriteCellData<Long> id = new WriteCellData<>(new BigDecimal(item.getId()));
id.setCommentData(commentData);
userInfoModel.setId(id);
//添加超链接
HyperlinkData hyperlinkData = new HyperlinkData();
hyperlinkData.setHyperlinkType(HyperlinkData.HyperlinkType.URL);
hyperlinkData.setAddress("http://www.baidu.com");
WriteCellData<String> userNickName = new WriteCellData<>(item.getUserNickname());
userNickName.setHyperlinkData(hyperlinkData);
userInfoModel.setUserNickName(userNickName);
userInfoModel.setUserGender(item.getUserGender());
userInfoModel.setUserBirth(item.getUserBirth());
return userInfoModel;
}).collect(Collectors.toList());
EasyExcel.write(EXPORT_FILE).head(UserInfoModel.class).sheet()
.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
.doWrite(modelList);
}
2.6导出图片到Excel
导出图片到Excel的需求很常见,有多种方法下面我将一一演示
模型类
如果你想通过获取图片的file、byte、流、Sting的方式获取图片然后导出到excel就分别指定他们的类型,但是这种方式不常见,因为图片一般我们都是存储在OSS中然后我们通过图片的URL来进行访问图片,所以我们指定图片为URL类型,还有一种情况存储在数据库的图片URL为Base64格式的,那么我们需要进行转换
/**
* 用户信息,模型。
*/
@Data
@ContentRowHeight(value = 50)
@ColumnWidth(value = 30)
public class UserInfoModel implements Serializable {
private static final long serialVersionUID = 1L;
@ExcelProperty(value = "File类型")
private File fileImage;
@ExcelProperty(value = "byte[]类型")
private byte[] byteImage;
@ExcelProperty(value = "InputStream类型")
private InputStream inputStreamImage;
@ExcelProperty(value = "URL类型")
private URL urlImage;
@ExcelProperty(value = "String类型", converter = Base64Convert1.class)
private String stringImage;
}
导出代码
如果图片通过File、byte、流则直接指定位置获取即可,如果是URL这种最常见则newURL进行指定导出、如果是通过String则需要通过convert转换成字节其实也是通过File获取然后转换这样,如果数据库图片的URL是Base64的那么也很简单我们只需自定义一个Convert,将Base64转成字节在将字节通过ConvertString类型进行返回就可以了;或者存到DB的是Base64编码后的URL然后我们可以查询出来转成URL在进行导出图片到excel
public static final String EXPORT_FILE = "C:\\Users\\Lenovo\\Desktop\\excel\\eazyExcel.xlsx";
@Test
@SneakyThrows
public void test() {
UserInfoModel userInfoModel = new UserInfoModel();
//文件类型
userInfoModel.setFileImage(new File("C:\\Users\\Lenovo\\Desktop\\excel\\20201124032511.png"));
//byte类型
userInfoModel.setByteImage(FileUtils.readFileToByteArray(new File("C:\\Users\\Lenovo\\Desktop\\excel\\20201124032511.png")));
//输入流类型
userInfoModel.setInputStreamImage(FileUtils.openInputStream(new File("C:\\Users\\Lenovo\\Desktop\\excel\\20201124032511.png")));
//URL类型
userInfoModel.setUrlImage(new URL("https://img-home.csdnimg.cn/images/20201124032511.png"));
//String类型
userInfoModel.setStringImage("iVBORw0KGgoAAAANSUhEUgAAAKAAAABYCAYAAAByDvxZAAAAAXNSR0IArs4c6QAAAERlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAAoKADAAQAAAABAAAAWAAAAADfqAIVAAAeZklEQVR4Ae1cB3hUx7W");
EasyExcel.write(EXPORT_FILE)
.head(UserInfoModel.class)
.sheet()
.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
.doWrite(Collections.singletonList(userInfoModel));
}
@SneakyThrows
@Test
public void testBase64(){
byte[] bytes = FileUtils.readFileToByteArray(new File("C:\\Users\\Lenovo\\Desktop\\excel\\20201124032511.png"));
String base64 = Base64.getEncoder().encodeToString(bytes);
System.out.println(base64);
}
2.7模板填充对象导出
我们上面学习到了通过模型类指定单元格进行导出,然后指定他的宽高、格式等等,那么这种方式大家发现是不是很麻烦,还需要去指定格式等等;现在我们可以在resouce目录下创建一个模板文件然后我们在模板中设置好格式,然后将数据填充到模板中这样就方便多了,这种方式适合简单的导出没什么要求,但是如果是出现一些字段上的需求比如超链接、批注、金钱符号等就无法满足。
模板样式
模型类
/**
* 用户信息,模型。
*/
@Data
public class UserInfoModel implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 用户编号。
*/
private Integer userCode;
/**
* 用户昵称。
*/
private String userNickname;
/**
* 用户积分。
*/
private Integer userScore;
/**
* 用户佣金。
*/
private BigDecimal userReward;
}
导出代码
/**
* 对象方式
*/
@Test
public void test1(){
InputStream inputStream = EasyExcelTest.class.getClassLoader().getResourceAsStream("export-template.xlsx");
UserInfoModel userInfoModel = new UserInfoModel();
userInfoModel.setUserCode(1001);
userInfoModel.setUserNickname("李佳伟");
userInfoModel.setUserScore(200);
userInfoModel.setUserReward(BigDecimal.valueOf(123.45));
EasyExcel.write(EXPORT_FILE).withTemplate(inputStream).sheet().doFill(userInfoModel);
}
导出样式
2.8模板填充对象列表导出
上面我们是添加一个对象然后导出,但是实际业务是多条数据的所以我们要实现添加列表的方式,与单个对象导出不同点就是模板中多加了个.
2.9模板组合填充
在开发中我们可能会遇到往一个表格中添加数据但是表格中有多个表的情况如图所示,然后我们还可能遇到横向填充的情况,这里为什么加个前缀dept或者user呢是为了在填充模型数据时好做区分
我们先获取excelWriter获取操作对象,然后获取添加的表writeSheet,如果是填充一个对象则直接fill如果是多个对象则需要new FillWrapper然后指定你填填充的前缀加数据,然后添加表writerSheet如果需要横向填充的话那就需要手动设置一个进行填充
FillConfig config = FillConfig.builder().direction(WriteDirectionEnum.HORIZONTAL).build(); //横向填充
@Test
public void test() {
InputStream exportTemplate = EasyExcelTest.class.getClassLoader().getResourceAsStream("export-template.xlsx");
try (ExcelWriter excelWriter = EasyExcel.write(EXPORT_FILE).withTemplate(exportTemplate).build()) {
WriteSheet writeSheet = EasyExcel.writerSheet().build();
// 公司信息。
Map<String, Object> companyInfo = new HashMap<>();
companyInfo.put("companyName", "北京XXX信息技术有限公司");
excelWriter.fill(companyInfo, writeSheet);
Map<String, Object> deptMap1 = new HashMap<>();
deptMap1.put("deptName", "研发部");
deptMap1.put("deptMaster","李佳伟");
deptMap1.put("deptContact","17045454589");
Map<String, Object> deptMap2 = new HashMap<>();
deptMap2.put("deptName", "财务部");
deptMap2.put("deptMaster","刘晓宇");
deptMap2.put("deptContact","17045454589");
FillConfig config = FillConfig.builder().direction(WriteDirectionEnum.HORIZONTAL).build(); //横向填充
List<Map<String, Object>> asList = Arrays.asList(deptMap1, deptMap2);
excelWriter.fill(new FillWrapper("dept",asList), config, writeSheet);
Map<String, Object> userInfo1 = new HashMap<>();
userInfo1.put("userCode", 1001);
userInfo1.put("userNickname", "张三");
userInfo1.put("userScore", 100);
userInfo1.put("userReward", BigDecimal.valueOf(123.45));
Map<String, Object> userInfo2 = new HashMap<>();
userInfo2.put("userCode", 1002);
userInfo2.put("userNickname", "李四");
userInfo2.put("userScore", 100);
userInfo2.put("userReward", BigDecimal.valueOf(123.45));
List<Map<String, Object>> mapList = Arrays.asList(userInfo1, userInfo2);
excelWriter.fill(new FillWrapper("user",mapList),writeSheet);
}
}
3.文件下载
文件下载其实我们在导出的时候通常会返回给前端excel的URL下载地址,然后前端直接根据这个URL进行下载就好了我们不用去管他,但是有时候有一些需求需要单独弄一个下载按钮,而不是直接导出的时候就下载了那么也就是如果单独弄下载按钮我们导出就不用返回URL了,直接提示用户稍后去下载中心查看下载就好了。
这里提供两种下载方式,一个是不提供URL进行下载就是可以通过前端传的数据然后去数据库查询出对应数据然后下载,那么如果这种方式也就相当于导出和下载结合了然后写到response里面,另外一种是通过URL进行下载这个URL就是存储在OSS网络的表格URL前端直接通过URL进行下载
未提供URL下载方式相当于导出下载结合
@GetMapping(value = "/export")
@SneakyThrows
public void export(HttpServletResponse response) {
List<UserInfoEntity> list = this.userInfoService.list();
response.setCharacterEncoding("UTF-8");
response.setContentType("application/vnd.ms-excel");
String fileName = URLEncoder.encode("用户信息", "UTF-8");
response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
ServletOutputStream outputStream = response.getOutputStream();
InputStream exportTemplate = Application.class.getClassLoader().getResourceAsStream("export-template.xlsx");
EasyExcel.write(outputStream)
.withTemplate(exportTemplate)
.sheet()
.doFill(list);
}
提供URL由前端直接去下载的方式
/**
* form表单提交,下载文件流
*
* @param response HttpServletResponse
* @param exportName 文件名
* @param exportUrl 下载文件URL
*/
@RequestMapping(value = "/download", method = RequestMethod.POST)
@ResponseBody
@PermissionCheck(skipAop = true)
public void download(HttpServletResponse response,
@RequestParam("exportName") String exportName,
@RequestParam("exportUrl") String exportUrl) {
// 设置强制下载不打开
response.setContentType("application/force-download");
response.setHeader("Content-Disposition", "attachment; filename=" + exportName);
int byteRead;
try {
URL url = new URL(exportUrl);
URLConnection conn = url.openConnection();
conn.setConnectTimeout(3 * 1000);
try (InputStream inStream = conn.getInputStream();
OutputStream outputStream = response.getOutputStream();) {
byte[] buffer = new byte[1204];
while ((byteRead = inStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, byteRead);
}
outputStream.flush();
}
} catch (Exception e) {
log.warn("download下载失败!", e);
}
}