how to add a picture to a .docx document with Apache POI XWPF in java

前端 未结 6 607
小蘑菇
小蘑菇 2020-11-30 08:32

I\'ve created a simple docx-Document, using Java POI 3.7. XWPF. Then, I added a picture by using the Method XWPFDocument.addpicture(byte[] arg0, int arg1).

相关标签:
6条回答
  • 2020-11-30 08:33

    I know this post is very old but still I am posting the answer so that all those who are searching for this answer can use it. For inserting the picture in the word document you have to write two programs. The first one is :-

    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();
    
        }
    
    }
    

    Now here I have used "CustomeXwPFDocument" in this code and you will not get any imports through any jar file so you have to add another .java class in your package. the code for "CustomXWPFDocument" class goes like this:-

    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 = "" +
                    "<a:graphic xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\">" +
                    "   <a:graphicData uri=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">" +
                    "      <pic:pic xmlns:pic=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">" +
                    "         <pic:nvPicPr>" +
                    "            <pic:cNvPr id=\"" + id + "\" name=\"Generated\"/>" +
                    "            <pic:cNvPicPr/>" +
                    "         </pic:nvPicPr>" +
                    "         <pic:blipFill>" +
                    "            <a:blip r:embed=\"" + blipId + "\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\"/>" +
                    "            <a:stretch>" +
                    "               <a:fillRect/>" +
                    "            </a:stretch>" +
                    "         </pic:blipFill>" +
                    "         <pic:spPr>" +
                    "            <a:xfrm>" +
                    "               <a:off x=\"0\" y=\"0\"/>" +
                    "               <a:ext cx=\"" + width + "\" cy=\"" + height + "\"/>" +
                    "            </a:xfrm>" +
                    "            <a:prstGeom prst=\"rect\">" +
                    "               <a:avLst/>" +
                    "            </a:prstGeom>" +
                    "         </pic:spPr>" +
                    "      </pic:pic>" +
                    "   </a:graphicData>" +
                    "</a:graphic>";
    
            //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");
        }
    }
    

    Use POI 3.9 jars for this program. The best URL is:- http://www.apache.org/dyn/closer.cgi/poi/release/bin/poi-bin-3.9-20121203.zip

    Now you are ready to fly. Best of luck.

    0 讨论(0)
  • 2020-11-30 08:40
    @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.
    
    0 讨论(0)
  • 2020-11-30 08:41

    The bug link that you've provided actually has a working solution: https://issues.apache.org/bugzilla/show_bug.cgi?id=49765#c15

    It requires some amount of hackery but I'm using it and it certainly works!

    0 讨论(0)
  • 2020-11-30 08:51

    I have used docx4j and found it to be working.I tried with POI but not able to make it work.Please find the code for using 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;
    

    }

    0 讨论(0)
  • 2020-11-30 08:55

    The elegant solution is coming, check out: https://issues.apache.org/bugzilla/show_bug.cgi?id=55476

    You can either wait till my patch gets accepted and released or try applying the patch to the latest POI SVN checkout (http://poi.apache.org/subversion.html, read only access link will work) and building POI jars from sources.

    The approach suggested by tsd.tom will work:

    XWPFParagraph par = docx.createParagraph();
    XWPFRun run = par.createRun();
    run.addPicture(pic, XWPFDocument.PICTURE_TYPE_JPEG, "logo.JPG",300,300); 
    
    0 讨论(0)
  • 2020-11-30 08:56

    Because XWPFRun.addPicture does not work (it damage xdoc file) i manage to picture like this:

        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 = "" + "<a:graphic xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\">"
                    + "   <a:graphicData uri=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">" + "      <pic:pic xmlns:pic=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">"
                    + "         <pic:nvPicPr>" + "            <pic:cNvPr id=\""
                    + id
                    + "\" name=\"Generated\"/>"
                    + "            <pic:cNvPicPr/>"
                    + "         </pic:nvPicPr>"
                    + "         <pic:blipFill>"
                    + "            <a:blip r:embed=\""
                    + blipId
                    + "\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\"/>"
                    + "            <a:stretch>"
                    + "               <a:fillRect/>"
                    + "            </a:stretch>"
                    + "         </pic:blipFill>"
                    + "         <pic:spPr>"
                    + "            <a:xfrm>"
                    + "               <a:off x=\"0\" y=\"0\"/>"
                    + "               <a:ext cx=\""
                    + width
                    + "\" cy=\""
                    + height
                    + "\"/>"
                    + "            </a:xfrm>"
                    + "            <a:prstGeom prst=\"rect\">"
                    + "               <a:avLst/>"
                    + "            </a:prstGeom>"
                    + "         </pic:spPr>"
                    + "      </pic:pic>" + "   </a:graphicData>" + "</a:graphic>";
    
            //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
                }
            }
        }
    
    }
    

    And running example:

     addPicture(filePath, xdoc.getNextPicNameNumber(Document.PICTURE_TYPE_JPEG), 100, 50, xRun);
    
    0 讨论(0)
提交回复
热议问题