如何使用Java中的Apache POI XWPF将图片添加到.docx文档中

我使用Java POI 3.7创建了一个简单的docx-Document。 XWPF。 然后,我使用方法XWPFDocument.addpicture(byte[] arg0, int arg1)添加了一张图片。

 XWPFDocument docx = new XWPFDocument(); XWPFParagraph par = docx.createParagraph(); XWPFRun run = par.createRun(); run.setText("Hello, World. This is my first java generated docx-file. Have fun."); run.setFontSize(13); InputStream pic = new FileInputStream("logo.jpg"); byte [] picbytes = IOUtils.toByteArray(pic); docx.addPicture(picbytes, Document.PICTURE_TYPE_JPEG); 

由于docx的文件大小增加,图片被“物理地”添加到文档中; 但它在MS Word中根本不显示。 似乎有一个参考文件中缺少的图片。

这样做的方法是什么? 如何用apache POI完成图片处理? Web上有更多教程,XWPF几乎没有任何文档或教程,它解释了段落,运行等的处理。

我在这里找到的唯一一件事是: https : //issues.apache.org/bugzilla/show_bug.cgi?id = 49765,但它根本没用。

提前谢谢了。

我知道这篇文章很老,但我仍然发布答案,以便所有搜索此答案的人都可以使用它。 要将图片插入word文档,您必须编写两个程序。 第一个是: –

 package org.word.POI; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.xwpf.usermodel.Document; import org.apache.poi.xwpf.usermodel.XWPFDocument; /* Romesh Soni soni.romesh@gmail.com */ public class TestCustom { public static void main(String []a) throws FileNotFoundException, IOException, InvalidFormatException { CustomXWPFDocument document = new CustomXWPFDocument(new FileInputStream(new File("C:\\Users\\amitabh\\Documents\\Apache POI\\Word File\\new.doc"))); FileOutputStream fos = new FileOutputStream(new File("C:\\Users\\amitabh\\Documents\\Apache POI\\Word File\\new.doc")); String blipId = document.addPictureData(new FileInputStream(new File("C:\\Users\\amitabh\\Pictures\\pics\\3.jpg")), Document.PICTURE_TYPE_JPEG); System.out.println(document.getNextPicNameNumber(Document.PICTURE_TYPE_JPEG)); //System.out.println(document.getNextPicNameNumber(Document.PICTURE_TYPE_JPEG)); document.createPicture(blipId,document.getNextPicNameNumber(Document.PICTURE_TYPE_JPEG), 500, 500); document.write(fos); fos.flush(); fos.close(); } } 

现在我在这个代码中使用了“CustomeXwPFDocument”,你不会通过任何jar文件获得任何导入,所以你必须在你的包中添加另一个.java类。 “CustomXWPFDocument”类的代码如下: –

 package org.word.POI; import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.apache.xmlbeans.XmlException; import org.apache.xmlbeans.XmlToken; import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps; import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D; import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTInline; import java.io.IOException; import java.io.InputStream; public class CustomXWPFDocument extends XWPFDocument { public CustomXWPFDocument(InputStream in) throws IOException { super(in); } public void createPicture(String blipId,int id, int width, int height) { final int EMU = 9525; width *= EMU; height *= EMU; //String blipId = getAllPictures().get(id).getPackageRelationship().getId(); CTInline inline = createParagraph().createRun().getCTR().addNewDrawing().addNewInline(); String picXml = "" + "" + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + ""; //CTGraphicalObjectData graphicData = inline.addNewGraphic().addNewGraphicData(); XmlToken xmlToken = null; try { xmlToken = XmlToken.Factory.parse(picXml); } catch(XmlException xe) { xe.printStackTrace(); } inline.set(xmlToken); //graphicData.set(xmlToken); inline.setDistT(0); inline.setDistB(0); inline.setDistL(0); inline.setDistR(0); CTPositiveSize2D extent = inline.addNewExtent(); extent.setCx(width); extent.setCy(height); CTNonVisualDrawingProps docPr = inline.addNewDocPr(); docPr.setId(id); docPr.setName("Picture " + id); docPr.setDescr("Generated"); } } 

对此程序使用POI 3.9jar。 最好的URL是: – http://www.apache.org/dyn/closer.cgi/poi/release/bin/poi-bin-3.9-20121203.zip

现在你准备好了。 祝你好运。

优雅的解决方案即将到来,请查看: https : //issues.apache.org/bugzilla/show_bug.cgi?id = 55476

您可以等到我的补丁被接受并发布或尝试将补丁应用到最新的POI SVN结账( http://poi.apache.org/subversion.html ,只读访问链接将起作用)并从源代码构建POI jar 。

tsd.tom建议的方法将起作用:

 XWPFParagraph par = docx.createParagraph(); XWPFRun run = par.createRun(); run.addPicture(pic, XWPFDocument.PICTURE_TYPE_JPEG, "logo.JPG",300,300); 

您提供的错误链接实际上有一个可行的解决方案: https : //issues.apache.org/bugzilla/show_bug.cgi?id = 49765#c15

它需要一些hackery,但我正在使用它,它肯定有效!

我使用了docx4j并发现它正在工作。我尝试使用POI但无法使其工作。请找到使用docx4j的代码。

 public static void main(String[] args) throws Exception { WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.createPackage(); //wordMLPackage.getMainDocumentPart().addStyledParagraphOfText("Title", "Hello World"); //wordMLPackage.getMainDocumentPart().addParagraphOfText("Text"); java.io.InputStream is = new java.io.FileInputStream("path\\to\\images.jpg"); // commons-io.jar byte[] bytes = IOUtils.toByteArray(is); String filenameHint = null; String altText = null; int id1 = 0; int id2 = 1; org.docx4j.wml.P p = newImage( wordMLPackage, bytes,filenameHint, altText,id1, id2,6000 ); // Now add our p to the document wordMLPackage.getMainDocumentPart().addObject(p); wordMLPackage.save(new java.io.File("helloworld.docx") ); is.close(); } public static org.docx4j.wml.P newImage( WordprocessingMLPackage wordMLPackage, byte[] bytes, String filenameHint, String altText, int id1, int id2, long cx) throws Exception { BinaryPartAbstractImage imagePart = BinaryPartAbstractImage.createImagePart(wordMLPackage, bytes); Inline inline = imagePart.createImageInline(filenameHint, altText,id1, id2, cx,false); // Now add the inline in w:p/w:r/w:drawing org.docx4j.wml.ObjectFactory factory = new org.docx4j.wml.ObjectFactory(); org.docx4j.wml.P p = factory.createP(); org.docx4j.wml.R run = factory.createR(); p.getContent().add(run); org.docx4j.wml.Drawing drawing = factory.createDrawing(); run.getContent().add(drawing); drawing.getAnchorOrInline().add(inline); return p; 

}

 @Pradeep Your code public static void main(String[] args) throws Exception { WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.createPackage(); //wordMLPackage.getMainDocumentPart().addStyledParagraphOfText("Title", "Hello World"); //wordMLPackage.getMainDocumentPart().addParagraphOfText("Text"); java.io.InputStream is = new java.io.FileInputStream("path\\to\\images.jpg"); // commons-io.jar byte[] bytes = IOUtils.toByteArray(is); String filenameHint = null; String altText = null; int id1 = 0; int id2 = 1; org.docx4j.wml.P p = newImage( wordMLPackage, bytes,filenameHint, altText,id1, id2,6000 ); // Now add our p to the document wordMLPackage.getMainDocumentPart().addObject(p); wordMLPackage.save(new java.io.File("helloworld.docx") ); is.close(); } public static org.docx4j.wml.P newImage( WordprocessingMLPackage wordMLPackage, byte[] bytes, String filenameHint, String altText, int id1, int id2, long cx) throws Exception { BinaryPartAbstractImage imagePart = BinaryPartAbstractImage.createImagePart(wordMLPackage, bytes); Inline inline = imagePart.createImageInline(filenameHint, altText,id1, id2, cx,false); // Now add the inline in w:p/w:r/w:drawing org.docx4j.wml.ObjectFactory factory = new org.docx4j.wml.ObjectFactory(); org.docx4j.wml.P p = factory.createP(); org.docx4j.wml.R run = factory.createR(); p.getContent().add(run); org.docx4j.wml.Drawing drawing = factory.createDrawing(); run.getContent().add(drawing); drawing.getAnchorOrInline().add(inline); return p; works , but all the above codes does not work, i tried it personally thanks, a lot. 

因为XWPFRun.addPicture不起作用(它损坏xdoc文件)我设法像这样:

  private void addPicture(final String fileName, final int id, int width, int height, final XWPFRun run) { FileInputStream fileInputStream = null; try { fileInputStream = new FileInputStream("/home/maq/ebworkspace/TeamForge_Tools/" + fileName); final String blipId = run.getDocument().addPictureData(fileInputStream, Document.PICTURE_TYPE_JPEG); final int EMU = 9525; width *= EMU; height *= EMU; //String blipId = getAllPictures().get(id).getPackageRelationship().getId(); final CTInline inline = run.getCTR().addNewDrawing().addNewInline(); final String picXml = "" + "" + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + ""; //CTGraphicalObjectData graphicData = inline.addNewGraphic().addNewGraphicData(); XmlToken xmlToken = null; xmlToken = XmlToken.Factory.parse(picXml); inline.set(xmlToken); //graphicData.set(xmlToken); inline.setDistT(0); inline.setDistB(0); inline.setDistL(0); inline.setDistR(0); final CTPositiveSize2D extent = inline.addNewExtent(); extent.setCx(width); extent.setCy(height); final CTNonVisualDrawingProps docPr = inline.addNewDocPr(); docPr.setId(id); docPr.setName("Picture " + id); docPr.setDescr("Generated"); } catch (final Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { //close streams if (fileInputStream != null) { try { fileInputStream.close(); } catch (final IOException ioEx) { //can be ignored } } } } 

并运行示例:

  addPicture(filePath, xdoc.getNextPicNameNumber(Document.PICTURE_TYPE_JPEG), 100, 50, xRun);