如何阻止HSSFWorkbook在Excel文件中嵌入系统用户名?
解决Apache POI生成XLS文件时携带系统用户名的问题
问题场景
使用Apache POI 5.2.0生成XLS文件时,通过strings工具检查发现文件中包含系统用户名(如christoffer.gamrath),即使清空文档摘要信息(作者、最后修改者等)也无法去除,导致不同机器生成的文件不一致。
原始生成代码:
void writeExcelFile() { var workbook = new HSSFWorkbook(); byte[] bytes; ByteArrayOutputStream bos = new ByteArrayOutputStream(); try { workbook.write(bos); bytes = bos.toByteArray(); } catch (IOException e) { throw new RuntimeException(e); } try { Files.write(Path.of("foo.xls"), bytes); } catch (IOException e) { throw new RuntimeException(e); } }
strings工具输出示例:
$ strings foo.xls christoffer.gamrath B Arial1 Arial1 Arial1 Arial "$"#,##0_);("$"#,##0) "$"#,##0_);[Red]("$"#,##0) "$"#,##0.00_);("$"#,##0.00) "$"#,##0.00_);[Red]("$"#,##0.00) _("$"* #,##0_);_("$"* (#,##0);_("$"* "-"_);_(@_) _(* #,##0_);_(* (#,##0);_(* "-"_);_(@_) _("$"* #,##0.00_);_("$"* (#,##0.00);_("$"* "-"??_);_(@_) _(* #,##0.00_);_(* (#,##0.00);_(* "-"??_);_(@_) Sheet1
问题原因
Apache POI的HSSF实现中,默认单元格样式会自动将系统用户名(取自System.getProperty("user.name"))作为样式的所有者存储,这部分信息不属于文档摘要属性,因此仅清空摘要信息无法去除。
解决方案
遍历工作簿中所有单元格样式,清空样式的所有者信息;同时保持清空文档摘要信息的操作,确保文件元数据干净。
修改后的代码:
void writeExcelFileWithoutUsername() { var workbook = new HSSFWorkbook(); // 遍历所有单元格样式,清空所有者信息 for (int i = 0; i < workbook.getNumCellStyles(); i++) { HSSFCellStyle style = workbook.getCellStyleAt(i); style.setOwner(""); } // 清空文档摘要信息 workbook.createInformationProperties(); SummaryInformation summaryInfo = workbook.getSummaryInformation(); if (summaryInfo != null) { summaryInfo.setAuthor(""); summaryInfo.setLastAuthor(""); summaryInfo.setTitle(""); summaryInfo.setSubject(""); summaryInfo.setKeywords(""); summaryInfo.setComments(""); } DocumentSummaryInformation docSummaryInfo = workbook.getDocumentSummaryInformation(); if (docSummaryInfo != null) { docSummaryInfo.setCompany(""); docSummaryInfo.setManager(""); } byte[] bytes; // 使用try-with-resources自动关闭流 try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) { workbook.write(bos); bytes = bos.toByteArray(); } catch (IOException e) { throw new RuntimeException(e); } try { Files.write(Path.of("foo_clean.xls"), bytes); } catch (IOException e) { throw new RuntimeException(e); } }
注意事项
如果后续代码中创建新的单元格样式,需要在创建后立即调用style.setOwner(""),避免新样式再次携带系统用户名:
HSSFCellStyle newStyle = workbook.createCellStyle(); newStyle.setOwner(""); // 其他样式配置...
内容的提问来源于stack exchange,提问作者cgamrath
相关产品推荐
相关产品推荐

