用DOCX4J合并word(docx)文档:如何复制图像



我需要用docx4j合并两个(或更多,但我们坚持两个)word文档(docx)。我的合并方法是从一个文档复制所有body子文档,然后附加到另一个文档。然后,我只是重新安排一些东西。我已经用了两年了,它很适合我的目的。

下面是一个简单的例子:

first.docx = simple text
Second.docx = simple text + image

    File first = new File("first.docx");
    File second = new File("second.docx");
    WordprocessingMLPackage f = WordprocessingMLPackage.load(first);
    WordprocessingMLPackage s = WordprocessingMLPackage.load(second);
    List body = s.getMainDocumentPart().getJAXBNodesViaXPath("//w:body", false);
    for(Object b : body){
        List filhos = ((org.docx4j.wml.Body)b).getContent();
        for(Object k : filhos)
            f.getMainDocumentPart().addObject(k);
    }
    List blips = s.getMainDocumentPart().getJAXBNodesViaXPath("//a:blip", false);
    for(Object el : blips){
        try {
            CTBlip blip = (CTBlip) el;
            RelationshipsPart parts = s.getMainDocumentPart().getRelationshipsPart();
            Relationship rel = parts.getRelationshipByID(blip.getEmbed());
            RelationshipsPart docRels = f.getMainDocumentPart().getRelationshipsPart();
            rel.setId(null);
            docRels.addRelationship(rel);
            blip.setEmbed(rel.getId());
            f.getMainDocumentPart().addTargetPart(s.getParts().getParts().get(new PartName("/word/"+rel.getTarget())));
        } catch (Exception ex){}
    }
    File saved = new File("saved.docx");
    f.save(saved);
    Desktop.getDesktop().open(saved);

问题是当我保存。出现以下错误:

    org.docx4j.openpackaging.exceptions.Docx4JException: Failed to add parts from relationships of /
at org.docx4j.openpackaging.io3.Save.addPartsFromRelationships(Save.java:390)
at org.docx4j.openpackaging.io3.Save.save(Save.java:192)
at org.docx4j.openpackaging.packages.OpcPackage.save(OpcPackage.java:441)
at org.docx4j.openpackaging.packages.OpcPackage.save(OpcPackage.java:406)
Caused by: org.docx4j.openpackaging.exceptions.Docx4JException: Failed to add parts from relationships of /word/document.xml
at org.docx4j.openpackaging.io3.Save.addPartsFromRelationships(Save.java:390)
at org.docx4j.openpackaging.io3.Save.savePart(Save.java:442)
at org.docx4j.openpackaging.io3.Save.addPartsFromRelationships(Save.java:385)
... 4 more
Caused by: org.docx4j.openpackaging.exceptions.Docx4JException: Failed to put binary part
at
org.docx4j.openpackaging.io3.stores.ZipPartStore.saveBinaryPart(ZipPartStore.java:398)
at org.docx4j.openpackaging.io3.Save.savePart(Save.java:418)
at org.docx4j.openpackaging.io3.Save.addPartsFromRelationships(Save.java:385)
... 6 more
Caused by: java.io.IOException: part '/word/media/image1.jpg' not found
at
org.docx4j.openpackaging.io3.stores.ZipPartStore.saveBinaryPart(ZipPartStore.java:361)
... 8 more
Exception in thread "main" org.docx4j.openpackaging.exceptions.Docx4JException: Failed to add parts from relationships of /
at org.docx4j.openpackaging.io3.Save.addPartsFromRelationships(Save.java:390)
at org.docx4j.openpackaging.io3.Save.save(Save.java:192)
at org.docx4j.openpackaging.packages.OpcPackage.save(OpcPackage.java:441)
at org.docx4j.openpackaging.packages.OpcPackage.save(OpcPackage.java:406)
Caused by: org.docx4j.openpackaging.exceptions.Docx4JException: Failed to add parts from relationships of /word/document.xml
at org.docx4j.openpackaging.io3.Save.addPartsFromRelationships(Save.java:390)
at org.docx4j.openpackaging.io3.Save.savePart(Save.java:442)
at org.docx4j.openpackaging.io3.Save.addPartsFromRelationships(Save.java:385)
... 4 more
Caused by: org.docx4j.openpackaging.exceptions.Docx4JException: Failed to put binary part
at
org.docx4j.openpackaging.io3.stores.ZipPartStore.saveBinaryPart(ZipPartStore.java:398)
at org.docx4j.openpackaging.io3.Save.savePart(Save.java:418)
at org.docx4j.openpackaging.io3.Save.addPartsFromRelationships(Save.java:385)
... 6 more
Caused by: java.io.IOException: part '/word/media/image1.jpg' not found
at
org.docx4j.openpackaging.io3.stores.ZipPartStore.saveBinaryPart(ZipPartStore.java:361)
... 8 more

这里有灯可以解决吗?

1)我不想要所有的大块,它很糟糕。2) docx4j的商业(企业)版本可以做到这一点,但我正在寻找自由/开源软件。

谢谢

在将s中的光点添加到f之前对其进行操作。换句话说,交换for循环的顺序。

那么在你的光点操作中,你需要做的是:

  • 获取感兴趣的部分
  • Rel = f.getMainDocumentPart().addTargetPart
  • 从rel.getId
  • 更新光点中的relId

现在将s的内容添加到f中。您可以使用addAll来完成这项工作,而不需要嵌套循环。而且只有一个body对象,所以不需要外部循环。

显然,这个答案仅限于处理CTBlip,然后只有嵌入的。关于合并docx文件的完整解决方案还有很多…

注意:我在docx4j Enterprise中编写了合并文档的代码

这里我们从帖子中组合了一个真正的工作代码:

List<Object> blips = s.getMainDocumentPart().getJAXBNodesViaXPath("//a:blip", false);
for (Object el : blips) {
    try {
        CTBlip blip = (CTBlip) el;
        RelationshipsPart parts = s.getMainDocumentPart().getRelationshipsPart();
        Relationship rel = parts.getRelationshipByID(blip.getEmbed());
        Part part = parts.getPart(rel);
        if (part instanceof ImagePngPart)
            System.out.println(((ImagePngPart) part).getBytes());
        if (part instanceof ImageJpegPart)
            System.out.println(((ImageJpegPart) part).getBytes());
        if (part instanceof ImageBmpPart)
            System.out.println(((ImageBmpPart) part).getBytes());
        if (part instanceof ImageGifPart)
            System.out.println(((ImageGifPart) part).getBytes());
        if (part instanceof ImageEpsPart)
            System.out.println(((ImageEpsPart) part).getBytes());
        if (part instanceof ImageTiffPart)
            System.out.println(((ImageTiffPart) part).getBytes());
        Relationship newrel = f.getMainDocumentPart().addTargetPart(part, AddPartBehaviour.RENAME_IF_NAME_EXISTS);
        blip.setEmbed(newrel.getId());
        f.getMainDocumentPart().addTargetPart(s.getParts().getParts().get(new PartName("/word/" + rel.getTarget())));
    } catch (Exception ex) {
        ex.printStackTrace();
    }
}

这个片段在docx中将带有装饰的图像从s文档传输到f文档。需要systs的原因我已经忘记了,但是没有它,lib无法确定图像的mime

最新更新