在使用 poi 插入图片的时候,遇到一个报错
org.apache.poi.openxml4j.exceptions.PartAlreadyExistsException: A part with the name '/xl/media/image1120.jpeg' already exists : Packages shall not contain equivalent part names and package implementers shall neither create nor recognize packages with equivalent part names. [M1.12]
大概意思是 Excel 新生成Part的Name 和 已经存在于Excel的一个 Part的Name 相同,没有办法解决所以报错了。
我的代码是这么写的,目的是往Excel里插入一张图片:
try {
Cell cell10 = row.createCell(10);
int pictureIndex = workbook.addPicture(model.getPicture(), Workbook.PICTURE_TYPE_JPEG);
CreationHelper helper = workbook.getCreationHelper();
Drawing drawing = sheet.createDrawingPatriarch();
ClientAnchor anchor = helper.createClientAnchor();
// 图片插入坐标
anchor.setCol1(10);
anchor.setRow1(row.getRowNum());
// 插入图片
Picture pict = drawing.createPicture(anchor, pictureIndex);
sheet.autoSizeColumn(10);
// 指定我想要的长宽
pict.resize(4, 1);
} catch(Exception exception) {
log.warn("fail to process picture of user {} brandgoodid {}", model.getUserId(), model.getBrandGoodId(), exception);
}
代码出问题的地方在这一行,问题是没检查 model.getPicture() 这个 byte[] 数组为不为 null。加上检查,就没有报错了。
int pictureIndex = workbook.addPicture(model.getPicture(), Workbook.PICTURE_TYPE_JPEG);
如果顺着源码,打断点看的话,问题出在了两个地方
第一个地方在 org.apache.poi.ooxml.POIXMLDocumentPart#createRelationship(org.apache.poi.ooxml.POIXMLRelation, org.apache.poi.ooxml.POIXMLFactory, int, boolean):
public final RelationPart createRelationship(POIXMLRelation descriptor, POIXMLFactory factory, int idx, boolean noRelation) {
try {
PackagePartName ppName = PackagingURIHelper.createPartName(descriptor.getFileName(idx));
PackageRelationship rel = null;
PackagePart part = this.packagePart.getPackage().createPart(ppName, descriptor.getContentType());
... ...
这边 ppName 和 null byte[] 对应的ppName 重复了。
因为这个ppName生成函数的入参 index 是根据 Excel 里所有图片的数量确定的。
第二处代码就是写入 null byte[] 的位置了。