如何在S3上传前处理Excel InputStream并删除多余首尾行
解决方案
完全可以在上传S3前直接内存修改Excel内容,不需要将文件落地存储,内存处理是性能更高、实现更简单的最优方案。你修改完Workbook对象后,只需将修改后的工作簿写入内存字节数组输出流,再转成字节输入流返回即可,全程无磁盘IO开销。
代码修改
1. 调整cleanFileBeforeS3Upload方法实现
public InputStream cleanFileBeforeS3Upload(InputStream inputStream, Definition definition) throws IOException, InvalidFormatException { // try-with-resources自动释放资源,避免泄漏 try ( InputStream originStream = inputStream; Workbook workbook = WorkbookFactory.create(originStream); ByteArrayOutputStream baos = new ByteArrayOutputStream() ) { var sheet = workbook.getSheetAt(0); ExcelUtils.removeLeadingAndTrailingRowsFromExcel(sheet, definition.getTrimLeadingRows(), definition.getTrimTrailingRows()); // 将修改后的工作簿写入内存输出流 workbook.write(baos); // 转换为输入流返回 return new ByteArrayInputStream(baos.toByteArray()); } }
2. 调整S3上传调用逻辑
需要替换原上传用的输入流,同时更新S3元数据的内容长度,避免上传报错:
// 先调用清洗方法得到处理后的输入流 InputStream cleanedExcelStream = cleanFileBeforeS3Upload(file.getInputStream(), definition); // 更新元数据的内容长度为清洗后的文件大小 metadata.setContentLength(cleanedExcelStream.available()); // 构造上传请求 var request = new PutObjectRequest(s3Properties.getBucket(), s3ObjectKey, cleanedExcelStream, metadata);
注意事项
- 内存占用控制:如果业务场景中上传的Excel普遍大于100M,建议添加上传文件大小前置校验,避免OOM风险。如果确实有超大Excel处理需求,再考虑临时文件落地方案,常规场景下100M以内的Excel内存处理完全稳定。
- 多Sheet适配:当前代码仅处理第一个Sheet,如果业务支持多Sheet文件,需要遍历所有Sheet执行行删除逻辑。
- 资源释放:示例中用try-with-resources自动关闭原始输入流、Workbook、字节输出流,无需手动释放资源,返回的ByteArrayInputStream由GC自动回收,不需要额外关闭。
内容的提问来源于stack exchange,提问作者Rafał Sokalski
相关产品推荐
相关产品推荐

