上传文件处理报错Excel、Word。org.apache.poi.openxml4j.exceptions.OLE2NotOfficeXmlFileException
在处理上传文件时,遇到报错日志显示 OLE2NotOfficeXmlFileException,原因是使用了错误的 API 处理不同格式的 Excel 文件。.xls 文件应使用 HSSF 类处理,而 .xlsx 文件应使用 XSSF 类。手动修改文件后缀可能导致文件内容与后缀不匹配,进而引发错误。解决方案是通过文件签名和扩展名校验,确保文件格式与扩展名一致,并在代码中使用正确的处理类。此外,后端
报错日志
org.apache.poi.openxml4j.exceptions.OLE2NotOfficeXmlFileException: The supplied data appears to be in the OLE2 Format. You are calling the part of POI that deals with OOXML (Office Open XML) Documents. You need to call a different part of POI to process this data (eg HSSF instead of XSSF)
原因分析
这个错误是因为你使用了处理 OOXML 格式文件(如 .xlsx)的 API 来处理 OLE2 格式文件(如 .xls)。Apache POI 对这两种不同格式的 Excel 文件需要使用不同的类进行处理:
.xls(OLE2 格式):使用 HSSF 相关类(如 HSSFWorkbook)
.xlsx(OOXML 格式):使用 XSSF 相关类(如 XSSFWorkbook)
排查
1.查看界面提示,根据提示信息,后端进行全局搜索,快速定位异常信息点。
2.没有明确信息,通过看日志+断点一步一步找到位置。
解决
1.找到报错位置,浏览上下代码信息。
2.根据报错日志,“使用了错误的类处理”,排查代码是否xls和xlsx对应正确的处理类。
3.处理类对应正确的话,问题就可能在文件本身。
实际情况
此问题在我遇到的项目中是部署项目、测试时提出的。描述是“excel文件手动修改后缀上传报错”。
然后百度查了一下,如图信息:
在excel、word中两种新老版本对应的处理类是不同的,而手动修改文件后缀会有一个问题就是,后缀改了xls(实际文件内容二进制仍然是xlsx),代码逻辑按照xls的HSS去处理了实际文件内容xlsx。
解决:利用文件格式的文件签名+后缀校验文件是否有过非法的后缀修改,写一个对校验在controller最外层拒绝此类文件提交。(当然也可以按照校验,校验出文件实际的格式,用对应的处理类进行处理)
代码示例
代码是放在utils包下的xx类,要使用需要编写service接口方法,service层调用验证方法,层层抛出异常,在controller层处理(return结果集)。
/**
* 验证MultipartFile的实际格式是否与扩展名一致(Excel文件严格验证,其他文件放行)
* @param file 待验证的MultipartFile
* @throws IOException 如果读取文件失败
* @throws IllegalArgumentException 如果Excel文件格式与扩展名不匹配
*/
public static void validateMultipartFileFormat(MultipartFile file) throws IOException {
if (file == null || file.isEmpty()) {
throw new IllegalArgumentException("上传的文件为空");
}
String fileName = file.getOriginalFilename();
if (fileName == null) {
throw new IllegalArgumentException("无法获取文件名");
}
String fileExtension = getFileExtension(fileName).toLowerCase();
// 只对Excel文件进行严格格式验证
if (fileExtension.equals("xls") || fileExtension.equals("xlsx")) {
// 读取文件前8个字节用于格式检测
byte[] header = new byte[8];
try (InputStream is = file.getInputStream()) {
int bytesRead = is.read(header);
if (bytesRead < 4) {
throw new IOException("文件内容不足,无法判断格式");
}
}
// 根据扩展名检查对应的文件格式
if (fileExtension.equals("xls") && !isOle2Format(header)) {
throw new IllegalArgumentException("文件扩展名是.xls,但实际不是Excel 97-2003格式");
}
if (fileExtension.equals("xlsx") && !isOoxmlFormat(header)) {
throw new IllegalArgumentException("文件扩展名是.xlsx,但实际不是Office Open XML格式");
}
}
// 其他文件类型直接放行,不进行格式验证
}
/**
* 检查文件头是否为OLE2格式(.xls)
*/
private static boolean isOle2Format(byte[] header) {
if (header.length < 8) return false;
// OLE2格式的前8字节签名: D0 CF 11 E0 A1 B1 1A E1
return header[0] == (byte) 0xD0 && header[1] == (byte) 0xCF && header[2] == (byte) 0x11 && header[3] == (byte) 0xE0 && header[4] == (byte) 0xA1 && header[5] == (byte) 0xB1 && header[6] == (byte) 0x1A && header[7] == (byte) 0xE1;
}
/**
* 检查文件头是否为OOXML格式(.xlsx)
*/
private static boolean isOoxmlFormat(byte[] header) {
if (header.length < 4) return false;
// OOXML格式是ZIP压缩包,前4字节签名: 50 4B 03 04
return header[0] == (byte) 0x50 && header[1] == (byte) 0x4B && header[2] == (byte) 0x03 && header[3] == (byte) 0x04;
}
/**
* 获取文件扩展名(不含点)
*/
private static String getFileExtension(String fileName) {
int dotIndex = fileName.lastIndexOf('.');
if (dotIndex == -1 || dotIndex == fileName.length() - 1) {
return "";
}
return fileName.substring(dotIndex + 1);
}
其他问题
上传文件,后端抛出异常,但是前端没有任何提示。

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐
所有评论(0)