From b471ab5edf72439cf6e37c4635c07e7a5fc08a4f Mon Sep 17 00:00:00 2001
From: xiaoyi <908147524@qq.com>
Date: 星期二, 03 十一月 2026 19:10:14 +0800
Subject: [PATCH] fix(excel): Excel 导入报错统一转为可读中文提示,不再出现「系统异常」500
---
yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java | 92 ++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 89 insertions(+), 3 deletions(-)
diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java
index b9ec1ed..e27d523 100644
--- a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java
+++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java
@@ -1,10 +1,18 @@
package cn.iocoder.yudao.framework.excel.core.util;
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.exceptions.ExceptionUtil;
+import cn.hutool.core.util.StrUtil;
import cn.idev.excel.ExcelWriter;
import cn.idev.excel.FastExcelFactory;
import cn.idev.excel.converters.longconverter.LongStringConverter;
+import cn.idev.excel.exception.ExcelAnalysisException;
+import cn.idev.excel.exception.ExcelCommonException;
+import cn.idev.excel.exception.ExcelDataConvertException;
import cn.iocoder.yudao.framework.common.util.http.HttpUtils;
+import lombok.extern.slf4j.Slf4j;
import cn.iocoder.yudao.framework.excel.core.handler.ColumnWidthMatchStyleStrategy;
+import cn.iocoder.yudao.framework.excel.core.handler.DateAsTextCellWriteHandler;
import cn.iocoder.yudao.framework.excel.core.handler.SelectSheetWriteHandler;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.multipart.MultipartFile;
@@ -13,11 +21,15 @@
import java.io.InputStream;
import java.util.List;
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.framework.excel.core.enums.ExcelErrorCodeConstants.*;
+
/**
* Excel 宸ュ叿绫�
*
- * @author 鑺嬮亾婧愮爜
+ * @author 瓒呯骇绠$悊鍛�
*/
+@Slf4j
public class ExcelUtils {
/**
@@ -55,13 +67,87 @@
response.setContentType("application/vnd.ms-excel;charset=UTF-8");
}
- public static <T> List<T> read(MultipartFile file, Class<T> head) throws IOException {
+ /**
+ * 杈撳嚭 Excel 妯℃澘锛堟棩鏈熸寜鏂囨湰娓叉煋锛�
+ *
+ * <p>涓� {@link #write} 鐨勫尯鍒細棰濆娉ㄥ唽浜� {@link DateAsTextCellWriteHandler}锛�
+ * 鎶� LocalDate / LocalDateTime 鍐欐垚 yyyy-MM-dd 鏂囨湰锛岃�屼笉鏄� Excel 鏃ユ湡搴忓垪鍙枫��
+ * 浠呯敤浜庛�屼笅杞藉鍏ユā鏉裤�嶏紝瀵煎叆瑙f瀽浠嶈蛋 {@link #read}锛屼笉鍙楀奖鍝嶃��</p>
+ */
+ public static <T> void writeTemplate(HttpServletResponse response, String filename, String sheetName,
+ Class<T> head, List<T> data) throws IOException {
+ ExcelWriter excelWriter = FastExcelFactory.write(response.getOutputStream(), head)
+ .autoCloseStream(false)
+ .registerWriteHandler(new ColumnWidthMatchStyleStrategy())
+ .registerWriteHandler(new SelectSheetWriteHandler(head))
+ .registerWriteHandler(new DateAsTextCellWriteHandler())
+ .registerConverter(new LongStringConverter())
+ .build();
+ try {
+ excelWriter.write(data, FastExcelFactory.writerSheet(sheetName).build());
+ } finally {
+ excelWriter.finish();
+ excelWriter.close();
+ }
+ response.addHeader("Content-Disposition", "attachment;filename=" + HttpUtils.encodeUtf8(filename));
+ response.setContentType("application/vnd.ms-excel;charset=UTF-8");
+ }
+
+ /**
+ * 璇诲彇 Excel 鏂囦欢
+ *
+ * <p>鎵�鏈夊鍏ユ帴鍙i兘缁忚繃杩欓噷锛屽洜姝ゅ湪杩欓噷缁熶竴鎶娿�屽潖鏂囦欢 / 绌烘枃浠� / 妯℃澘涓嶅尮閰� / 鍗曞厓鏍兼牸寮忛敊銆�
+ * 绛夊悇绉嶅簳灞傚紓甯革紝杞崲鎴愬彲璇荤殑涓枃鎻愮ず锛圫erviceException锛夈��
+ * 杩欐牱涓氬姟鎺ュ彛涓嶅繀鍚勮嚜鍐� try-catch锛屼篃涓嶄細鍐嶅嚭鐜板惈绯婄殑銆岀郴缁熷紓甯搞��500銆�</p>
+ *
+ * @param file Excel 鏂囦欢
+ * @param head 琛ㄥご瀵瑰簲鐨� VO 绫�
+ * @return 瑙f瀽缁撴灉
+ */
+ public static <T> List<T> read(MultipartFile file, Class<T> head) {
+ // 1. 鏂囦欢鏈韩涓虹┖
+ if (file == null || file.isEmpty()) {
+ throw exception(EXCEL_FILE_EMPTY);
+ }
+ // 2. 瑙f瀽锛堥�愮被璇嗗埆寮傚父锛岀粰鍑哄彲璇绘彁绀猴級
+ List<T> list;
// 鍙傝�� https://t.zsxq.com/zM77F 甯栧瓙锛屽鍔� try 澶勭悊锛屽吋瀹� windows 鍦烘櫙
try (InputStream inputStream = file.getInputStream()) {
- return FastExcelFactory.read(inputStream, head, null)
+ list = FastExcelFactory.read(inputStream, head, null)
.autoCloseStream(false) // 涓嶈鑷姩鍏抽棴锛屼氦缁� Servlet 鑷繁澶勭悊
.doReadAllSync();
+ } catch (IOException ex) {
+ log.warn("[read][Excel 鏂囦欢璇诲彇澶辫触锛屾枃浠跺悕({})]", file.getOriginalFilename(), ex);
+ throw exception(EXCEL_FILE_READ_FAILED);
+ } catch (ExcelDataConvertException ex) {
+ // 鍗曞厓鏍兼暟鎹牸寮忎笉瀵癸紝渚嬪鏂囨湰鍒楀~浜嗘暟瀛椼�佹棩鏈熷垪濉簡涔辩爜
+ String detail = StrUtil.blankToDefault(ex.getMessage(), "鍐呭涓庡垪绫诲瀷涓嶅尮閰�");
+ log.warn("[read][Excel 鍗曞厓鏍兼暟鎹牸寮忛敊璇紝琛�({}) 鍒�({})]", ex.getRowIndex(), ex.getColumnIndex(), ex);
+ throw exception(EXCEL_DATA_CONVERT_FAILED,
+ (ex.getRowIndex() == null ? 0 : ex.getRowIndex()) + 1,
+ (ex.getColumnIndex() == null ? 0 : ex.getColumnIndex()) + 1,
+ StrUtil.maxLength(detail, 60));
+ } catch (ExcelAnalysisException ex) {
+ // 鏂囦欢鎹熷潖銆佸姞瀵嗐�佷笉鏄湡姝g殑 Excel銆佽〃澶翠笌妯℃澘瀵逛笉涓婄瓑
+ String rootMsg = StrUtil.blankToDefault(ExceptionUtil.getRootCauseMessage(ex), "");
+ log.warn("[read][Excel 瑙f瀽澶辫触锛屾枃浠跺悕({})锛屽師鍥�({})]", file.getOriginalFilename(), rootMsg, ex);
+ if (StrUtil.containsAnyIgnoreCase(rootMsg, "head", "Can not find", "autoTrim", "Convert")) {
+ throw exception(EXCEL_HEAD_NOT_MATCH);
+ }
+ throw exception(EXCEL_TEMPLATE_NOT_MATCH);
+ } catch (ExcelCommonException ex) {
+ log.warn("[read][Excel 閫氱敤寮傚父锛屾枃浠跺悕({})]", file.getOriginalFilename(), ex);
+ throw exception(EXCEL_FILE_READ_FAILED);
+ } catch (Exception ex) {
+ // 鍏滃簳锛氫换浣曟湭棰勬枡鐨勮В鏋愬紓甯搁兘杞垚鍙鎻愮ず锛岄伩鍏嶇洿鎺� 500銆岀郴缁熷紓甯搞��
+ log.warn("[read][Excel 瑙f瀽鍑虹幇鏈鏈熷紓甯革紝鏂囦欢鍚�({})]", file.getOriginalFilename(), ex);
+ throw exception(EXCEL_FILE_READ_FAILED);
}
+ // 3. 瑙f瀽鍑烘潵鏄┖琛紙鍙湁琛ㄥご銆佹病鏈夋暟鎹锛�
+ if (CollUtil.isEmpty(list)) {
+ throw exception(EXCEL_FILE_EMPTY_CONTENT);
+ }
+ return list;
}
}
--
Gitblit v1.9.3