feat(xlsx): 添加Excel导出工具类并重构导出功能
- 新增KitXlsxExportDataTransferRowHandler接口用于数据转换 - 新增KitXlsxExportUtil工具类提供统一的Excel导出功能 - 添加多个ExportRowVo类用于导出数据映射 - 重构部门、字典、岗位、菜单等模块的导出功能使用新工具类 - 添加SystemYesOrNoChConst和SystemZhConst常量接口 - 标记KitFileUtil.downloadExcel方法为废弃 - 优化文件名验证逻辑和字符串类型判断
This commit is contained in:
+5
-11
@@ -13,7 +13,6 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cn.odboy.util;
|
||||
|
||||
import static cn.odboy.constant.SystemConst.SYMBOL_ADD;
|
||||
@@ -44,6 +43,7 @@ import java.util.Date;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.poi.util.IOUtils;
|
||||
@@ -80,7 +80,6 @@ public final class KitFileUtil extends cn.hutool.core.io.FileUtil {
|
||||
* 定义KB的计算常量
|
||||
*/
|
||||
private static final int KB = 1024;
|
||||
|
||||
/**
|
||||
* 格式化小数
|
||||
*/
|
||||
@@ -185,6 +184,7 @@ public final class KitFileUtil extends cn.hutool.core.io.FileUtil {
|
||||
/**
|
||||
* 导出excel
|
||||
*/
|
||||
@Deprecated
|
||||
public static void downloadExcel(List<Map<String, Object>> list, HttpServletResponse response) throws IOException {
|
||||
String tempPath = SYS_TEM_DIR + IdUtil.fastSimpleUUID() + ".xlsx";
|
||||
File file = new File(tempPath);
|
||||
@@ -193,7 +193,8 @@ public final class KitFileUtil extends cn.hutool.core.io.FileUtil {
|
||||
List<Map<String, Object>> sanitizedList = list.parallelStream().map(map -> {
|
||||
Map<String, Object> sanitizedMap = new LinkedHashMap<>();
|
||||
map.forEach((key, value) -> {
|
||||
if (value instanceof String strValue) {
|
||||
if (value instanceof String) {
|
||||
String strValue = (String) value;
|
||||
// 检查并处理以特殊字符开头的值
|
||||
if (strValue.startsWith(SYMBOL_EQUAL) || strValue.startsWith(SYMBOL_ADD) ||
|
||||
strValue.startsWith(SYMBOL_SUBTRACT) || strValue.startsWith(SYMBOL_AT)) {
|
||||
@@ -206,7 +207,7 @@ public final class KitFileUtil extends cn.hutool.core.io.FileUtil {
|
||||
}
|
||||
});
|
||||
return sanitizedMap;
|
||||
}).toList();
|
||||
}).collect(Collectors.toList());
|
||||
// 一次性写出内容, 使用默认样式,强制输出标题
|
||||
writer.write(sanitizedList, true);
|
||||
SXSSFSheet sheet = (SXSSFSheet) writer.getSheet();
|
||||
@@ -363,10 +364,8 @@ public final class KitFileUtil extends cn.hutool.core.io.FileUtil {
|
||||
public static String verifyFilename(String fileName) {
|
||||
// 过滤掉特殊字符
|
||||
fileName = fileName.replaceAll("[\\\\/:*?\"<>|~\\s]", "");
|
||||
|
||||
// 去掉文件名开头和结尾的空格和点
|
||||
fileName = fileName.trim().replaceAll("^[. ]+|[. ]+$", "");
|
||||
|
||||
// 不允许文件名超过255(在Mac和Linux中)或260(在Windows中)个字符
|
||||
int maxFileNameLength = 255;
|
||||
if (System.getProperty(SystemConst.PROPERTY_OS_NAME).startsWith(SystemConst.OS_NAME_WINDOWS)) {
|
||||
@@ -375,20 +374,15 @@ public final class KitFileUtil extends cn.hutool.core.io.FileUtil {
|
||||
if (fileName.length() > maxFileNameLength) {
|
||||
fileName = fileName.substring(0, maxFileNameLength);
|
||||
}
|
||||
|
||||
// 过滤掉控制字符
|
||||
fileName = fileName.replaceAll("[\\p{Cntrl}]", "");
|
||||
|
||||
// 过滤掉 ".." 路径
|
||||
fileName = fileName.replaceAll("\\.{2,}", "");
|
||||
|
||||
// 去掉文件名开头的 ".."
|
||||
fileName = fileName.replaceAll("^\\.+/", "");
|
||||
|
||||
// 保留文件名中最后一个 "." 字符,过滤掉其他 "."
|
||||
fileName = fileName.replaceAll("^(.*)(\\.[^.]*)$", "$1").replaceAll("\\.", "") +
|
||||
fileName.replaceAll("^(.*)(\\.[^.]*)$", "$2");
|
||||
|
||||
return fileName;
|
||||
}
|
||||
|
||||
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
package cn.odboy.util.xlsx;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface KitXlsxExportDataTransferRowHandler<O, T> {
|
||||
|
||||
List<T> doHandler(O o);
|
||||
}
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
package cn.odboy.util.xlsx;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.date.DatePattern;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.idev.excel.FastExcel;
|
||||
import cn.odboy.framework.exception.BadRequestException;
|
||||
import java.io.IOException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.experimental.UtilityClass;
|
||||
|
||||
/**
|
||||
* xlsx文件导出工具
|
||||
*
|
||||
* @author odboy
|
||||
* @date 2025-12-29
|
||||
*/
|
||||
@UtilityClass
|
||||
public class KitXlsxExportUtil {
|
||||
|
||||
/**
|
||||
* @param response HttpServletResponse
|
||||
* @param title 标题
|
||||
* @param dataObjectList 数据源,一般为从数据库直接查询的数据
|
||||
* @param targetClazz 目标对象Class
|
||||
* @param rowHandler 数据对象 -> 目标对象 映射逻辑
|
||||
* @param <O> 数据源对象类型
|
||||
* @param <T> 目标对象类型
|
||||
* @throws IOException
|
||||
*/
|
||||
public static <O, T> void exportFile(HttpServletResponse response, String title, List<O> dataObjectList, Class<T> targetClazz, KitXlsxExportDataTransferRowHandler<O, T> rowHandler) throws IOException {
|
||||
if (response == null) {
|
||||
throw new BadRequestException("参数 HttpServletResponse(response) 必填");
|
||||
}
|
||||
if (CollUtil.isEmpty(dataObjectList)) {
|
||||
throw new BadRequestException("参数 数据源(dataObjectList) 必填");
|
||||
}
|
||||
if (StrUtil.isBlank(title)) {
|
||||
throw new BadRequestException("参数 标题(title) 必填");
|
||||
}
|
||||
String sheetName = DateUtil.format(new Date(), DatePattern.PURE_DATETIME_MS_PATTERN);
|
||||
List<T> resultList = new ArrayList<>();
|
||||
for (O o : dataObjectList) {
|
||||
List<T> rows = rowHandler.doHandler(o);
|
||||
resultList.addAll(rows);
|
||||
}
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setCharacterEncoding("utf-8");
|
||||
String fileName = URLEncoder.encode(sheetName + "_" + title, StandardCharsets.UTF_8);
|
||||
response.setHeader("Content-disposition",
|
||||
"attachment;filename*=utf-8''" + fileName + ".xlsx");
|
||||
FastExcel.write(response.getOutputStream(), targetClazz)
|
||||
.sheet(sheetName)
|
||||
.doWrite(resultList);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user