package cn.flightfeather.supervision.docx4j.simpleDemo; import org.docx4j.XmlUtils; import org.docx4j.jaxb.Context; import org.docx4j.openpackaging.packages.WordprocessingMLPackage; import org.docx4j.openpackaging.parts.PartName; import org.docx4j.openpackaging.parts.WordprocessingML.HeaderPart; import org.docx4j.openpackaging.parts.WordprocessingML.ImagePngPart; import org.docx4j.openpackaging.parts.relationships.RelationshipsPart.AddPartBehaviour; import org.docx4j.relationships.Relationship; import org.docx4j.wml.Hdr; import org.docx4j.wml.ObjectFactory; import org.docx4j.wml.SectPr; import java.io.File; import java.io.IOException; /** * * A watermark is set via the headers. * * This is different to w:document/w:background (see BackgroundImage sample for that, * though this WatermarkPicture is probably what you want.) * * @author jharrop */ public class WatermarkPicture { static String DOCX_OUT; public static void main(String[] args) throws Exception { // The image to add imageFile = new File(System.getProperty("user.dir") + "/src/main/resources/images/greentick.png" ); // Save it to DOCX_OUT = System.getProperty("user.dir") + "/OUT_WaterMarkPicture.docx"; WatermarkPicture sample = new WatermarkPicture(); sample.addWaterMark(); } static ObjectFactory factory = Context.getWmlObjectFactory(); static File imageFile; private byte[] image; private WordprocessingMLPackage wordMLPackage; public void addWaterMark() throws Exception { image = this.getImage(); wordMLPackage = WordprocessingMLPackage .createPackage(); // A watermark is defined in the headers, which are in turn set in sectPr wordMLPackage.getMainDocumentPart().getContents().getBody().setSectPr( createSectPr() ); File f = new File(DOCX_OUT); wordMLPackage.save(f); } private SectPr createSectPr() throws Exception { String openXML = "" // Word adds the background image in each of 3 header parts + "" + "" + "" // Word adds empty footer parts when you create a watermark, but its not necessary // + "" // + "" // + "" + "" + "" + "" + "" +""; return (SectPr)XmlUtils.unmarshalString(openXML); } private Relationship createHeaderPart(String nameSuffix) throws Exception { HeaderPart headerPart = new HeaderPart(new PartName("/word/header-" + nameSuffix + ".xml")); Relationship rel = wordMLPackage.getMainDocumentPart().addTargetPart(headerPart); setHdr( headerPart); return rel; } private void setHdr(HeaderPart headerPart) throws Exception { ImagePngPart imagePart = new ImagePngPart(new PartName("/media/background.png")); imagePart.setBinaryData(image); Relationship rel = headerPart.addTargetPart(imagePart, AddPartBehaviour.REUSE_EXISTING); // the one image is shared by the 3 header parts String openXML = "" + "" + "" + "" +"" + "" + "" + "" +"" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" +"" + "" + "" +"" + "" + "" +"" +"" +"" +"" +""; Hdr hdr = (Hdr)XmlUtils.unmarshalString(openXML); headerPart.setJaxbElement(hdr); } private byte[] getImage() throws IOException { // Our utility method wants that as a byte array java.io.InputStream is = new java.io.FileInputStream(imageFile ); long length = imageFile.length(); // You cannot create an array using a long type. // It needs to be an int type. if (length > Integer.MAX_VALUE) { System.out.println("File too large!!"); } byte[] bytes = new byte[(int)length]; int offset = 0; int numRead = 0; while (offset < bytes.length && (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) { offset += numRead; } // Ensure all the bytes have been read in if (offset < bytes.length) { System.out.println("Could not completely read file "+imageFile.getName()); } is.close(); return bytes; } }