From 1e46b9eab01663ac5d114d0e450e1f43829e96ab Mon Sep 17 00:00:00 2001 From: MMS Date: Mon, 15 Sep 2025 20:26:27 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8DExcelUil=20=E5=AF=BC=E5=87=BA?= =?UTF-8?q?=E4=BA=8ESpringboot=203.2.6=20=E7=89=88=E6=9C=AC=E4=B8=8D?= =?UTF-8?q?=E5=85=BC=E5=AE=B9=E9=97=AE=E9=A2=98=EF=BC=8C=E6=8C=87=E5=AE=9A?= =?UTF-8?q?poi?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../system/controller/SysUserController.java | 12 +- mms-modules/mms-framework/pom.xml | 9 ++ .../sxpcwlkj/framework/utils/ExcelUtil.java | 117 +++++++++++++++++- pom.xml | 24 ++++ 4 files changed, 154 insertions(+), 8 deletions(-) diff --git a/mms-admin/src/main/java/com/sxpcwlkj/system/controller/SysUserController.java b/mms-admin/src/main/java/com/sxpcwlkj/system/controller/SysUserController.java index c28218a..efae61f 100644 --- a/mms-admin/src/main/java/com/sxpcwlkj/system/controller/SysUserController.java +++ b/mms-admin/src/main/java/com/sxpcwlkj/system/controller/SysUserController.java @@ -143,13 +143,15 @@ public class SysUserController extends BaseController { * 导出系统用户 */ @MssSafety - @Transactional + //@Transactional @SaCheckPermission("system:user:export") @PostMapping("/export") - public void export(SysUserBo user, PageQuery pageQuery,HttpServletResponse response) throws IOException { - List list= baseService.selectPageUserList(user, pageQuery).getRows(); - List data= MapstructUtil.convert(list,SysUserExportVo.class); - ExcelUtil.export(response, SysUserExportVo.class, "系统用户",data); + public void export(SysUserBo user, PageQuery pageQuery, HttpServletResponse response) throws IOException { + List list = baseService.selectPageUserList(user, pageQuery).getRows(); + List data = MapstructUtil.convert(list, SysUserExportVo.class); + + // 使用封装后的安全导出方法 + ExcelUtil.safeExport(response, SysUserExportVo.class, "系统用户", data, pageQuery); } /** diff --git a/mms-modules/mms-framework/pom.xml b/mms-modules/mms-framework/pom.xml index 635f5a5..7d90b4d 100644 --- a/mms-modules/mms-framework/pom.xml +++ b/mms-modules/mms-framework/pom.xml @@ -97,6 +97,15 @@ com.alibaba easyexcel + + + org.apache.poi + poi + + + org.apache.poi + poi-ooxml + commons-io diff --git a/mms-modules/mms-framework/src/main/java/com/sxpcwlkj/framework/utils/ExcelUtil.java b/mms-modules/mms-framework/src/main/java/com/sxpcwlkj/framework/utils/ExcelUtil.java index 2a53432..71999d0 100644 --- a/mms-modules/mms-framework/src/main/java/com/sxpcwlkj/framework/utils/ExcelUtil.java +++ b/mms-modules/mms-framework/src/main/java/com/sxpcwlkj/framework/utils/ExcelUtil.java @@ -2,7 +2,9 @@ package com.sxpcwlkj.framework.utils; import com.alibaba.excel.EasyExcel; import com.alibaba.excel.read.listener.PageReadListener; +import com.sxpcwlkj.datasource.entity.page.PageQuery; import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; @@ -18,6 +20,7 @@ import java.util.Set; * @author mmsAdmin * @Doc mmsadmin.cn */ +@Slf4j public class ExcelUtil { @@ -32,7 +35,30 @@ public class ExcelUtil { response.setCharacterEncoding("utf-8"); String fileName = URLEncoder.encode("模版文件", "UTF-8"); response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx"); - EasyExcel.write(response.getOutputStream(), clazz).sheet("模板").doWrite(new ArrayList<>()); + + // 设置防止浏览器缓存的响应头 + response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate"); + response.addHeader("Cache-Control", "post-check=0, pre-check=0"); + response.setHeader("Pragma", "no-cache"); + + try { + EasyExcel.write(response.getOutputStream(), clazz) + .autoCloseStream(false) + .useDefaultStyle(false) + .inMemory(true) + .sheet("模板") + .doWrite(new ArrayList<>()); + } catch (Exception e) { + e.printStackTrace(); + try { + response.reset(); + response.setContentType("application/json"); + response.setCharacterEncoding("utf-8"); + response.getWriter().println("{\"code\":500,\"msg\":\"下载模板失败,请联系管理员\"}"); + } catch (Exception ex) { + // 忽略重置响应时的异常 + } + } } /** @@ -47,7 +73,30 @@ public class ExcelUtil { response.setCharacterEncoding("utf-8"); String fileName = URLEncoder.encode(sheetName, "UTF-8"); response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx"); - EasyExcel.write(response.getOutputStream(), clazz).sheet("模板").doWrite(new ArrayList<>()); + + // 设置防止浏览器缓存的响应头 + response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate"); + response.addHeader("Cache-Control", "post-check=0, pre-check=0"); + response.setHeader("Pragma", "no-cache"); + + try { + EasyExcel.write(response.getOutputStream(), clazz) + .autoCloseStream(false) + .useDefaultStyle(false) + .inMemory(true) + .sheet(sheetName) + .doWrite(new ArrayList<>()); + } catch (Exception e) { + e.printStackTrace(); + try { + response.reset(); + response.setContentType("application/json"); + response.setCharacterEncoding("utf-8"); + response.getWriter().println("{\"code\":500,\"msg\":\"下载模板失败,请联系管理员\"}"); + } catch (Exception ex) { + // 忽略重置响应时的异常 + } + } } /** @@ -62,7 +111,34 @@ public class ExcelUtil { response.setCharacterEncoding("utf-8"); String fileName = URLEncoder.encode(sheetName, "UTF-8"); response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx"); - EasyExcel.write(response.getOutputStream(), clazz).sheet("模板").doWrite(list); + + // 设置防止浏览器缓存的响应头 + response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate"); + response.addHeader("Cache-Control", "post-check=0, pre-check=0"); + response.setHeader("Pragma", "no-cache"); + + try { + // 使用不依赖POI内部方法的配置 + EasyExcel.write(response.getOutputStream(), clazz) + .autoCloseStream(false) // 不自动关闭流 + .useDefaultStyle(false) // 不使用默认样式,避免调用可能不存在的POI方法 + .inMemory(true) // 使用内存模式,避免临时文件IO问题 + .sheet(sheetName) // 使用传入的sheetName作为表名 + .doWrite(list); + } catch (Exception e) { + // 记录异常 + e.printStackTrace(); + + // 重置响应并返回错误信息 + try { + response.reset(); + response.setContentType("application/json"); + response.setCharacterEncoding("utf-8"); + response.getWriter().println("{\"code\":500,\"msg\":\"导出Excel失败,请联系管理员\"}"); + } catch (Exception ex) { + // 忽略重置响应时的异常 + } + } } /** @@ -94,4 +170,39 @@ public class ExcelUtil { EasyExcel.read(file.getInputStream(), clazz, new PageReadListener(data::addAll)).sheet().doRead(); return data; } + + /** + * 安全导出数据(封装分页限制和异常处理) + * + * @param response 响应对象 + * @param clazz 数据类 + * @param sheetName 表名 + * @param data 数据列表 + * @param pageQuery 分页查询条件 + */ + public static void safeExport(HttpServletResponse response, Class clazz, String sheetName, List data, PageQuery pageQuery) throws IOException { + // 限制导出数据量,避免内存溢出 + if (pageQuery == null) { + pageQuery = new PageQuery(); + } + // 设置合理的导出数量上限 + if (pageQuery.getPageSize() > 5000 || pageQuery.getPageSize() <= 0) { + pageQuery.setPageSize(5000); + } + + try { + export(response, clazz, sheetName, data); + } catch (Exception e) { + log.error("导出Excel异常", e); + try { + // 重置响应并返回错误信息 + response.reset(); + response.setContentType("application/json"); + response.setCharacterEncoding("utf-8"); + response.getWriter().println("{\"code\":500,\"msg\":\"导出失败,请联系管理员\"}"); + } catch (Exception ex) { + log.error("处理导出异常时出错", ex); + } + } + } } diff --git a/pom.xml b/pom.xml index 84c7578..439446d 100644 --- a/pom.xml +++ b/pom.xml @@ -47,6 +47,7 @@ 0.15.0 2.17.0 4.0.3 + 4.1.2 @@ -282,6 +283,29 @@ com.alibaba easyexcel ${easyexcel.version} + + + + org.apache.poi + poi + + + org.apache.poi + poi-ooxml + + + + + + + org.apache.poi + poi + ${poi.version} + + + org.apache.poi + poi-ooxml + ${poi.version}