/** * Create an image part from the provided byte array, attach it to the source part (eg the main * document part, a header part etc), and return it. * * <p>Works for both docx and pptx. * * <p>Knowing the MIME type allows you to avoid ImageInfo, but you'll probably also need to know * the image dimensions * * @param opcPackage * @param sourcePart * @param bytes * @param mime MIME type eg image/png * @return * @throws Exception @Since 3.0.1 */ public static BinaryPartAbstractImage createImagePart( OpcPackage opcPackage, Part sourcePart, byte[] bytes, String mime) throws Exception { String ext = mimeToExt(mime); if (mime == null || ext == null) { log.warn("Null or unknown mime type; image introspection required!"); return createImagePart(opcPackage, sourcePart, bytes); } ContentTypeManager ctm = opcPackage.getContentTypeManager(); // Ensure the relationships part exists if (sourcePart.getRelationshipsPart() == null) { RelationshipsPart.createRelationshipsPartForPart(sourcePart); } String proposedRelId = sourcePart.getRelationshipsPart().getNextId(); BinaryPartAbstractImage imagePart = (BinaryPartAbstractImage) ctm.newPartForContentType( mime, createImageName(opcPackage, sourcePart, proposedRelId, ext), null); log.debug( "created part " + imagePart.getClass().getName() + " with name " + imagePart.getPartName().toString()); imagePart.setBinaryData(bytes); imagePart.rels.add(sourcePart.addTargetPart(imagePart, proposedRelId)); return imagePart; }
/** * Create a linked image part, and attach it as a rel of the specified source part (eg a header * part). * * <p>The current behaviour is that the part is added to the package, but since the target mode of * the rel is external, the part is redundant. * * @param wordMLPackage * @param sourcePart * @param url * @return * @throws Exception */ public static BinaryPartAbstractImage createLinkedImagePart( OpcPackage opcPackage, Part sourcePart, URL url) throws Exception { log.debug("Incoming url for linked image: " + url.toString()); ImageInfo info = ensureFormatIsSupported(url, null, null, false); // final param doesn't matter in this case ContentTypeManager ctm = opcPackage.getContentTypeManager(); String proposedRelId = sourcePart.getRelationshipsPart().getNextId(); // In order to ensure unique part name, // idea is to use the relId, which ought to be unique String ext = info.getMimeType().substring(info.getMimeType().indexOf("/") + 1); BinaryPartAbstractImage imagePart = (BinaryPartAbstractImage) ctm.newPartForContentType( info.getMimeType(), createImageName(opcPackage, sourcePart, proposedRelId, ext), null); // NB: contents never populated log.debug( "created part " + imagePart.getClass().getName() + " with name " + imagePart.getPartName().toString()); imagePart.rels.add( sourcePart.addTargetPart( imagePart)); // want to create rel with suitable name; side effect is to add part imagePart.getRelLast().setTargetMode("External"); opcPackage.getExternalResources().put(imagePart.getExternalTarget(), imagePart); // if (!url.getProtocol().equals("file") && new File(url.toString() ).isFile()) { // imagePart.rel.setTarget("file:///" + url); // } else { // imagePart.rel.setTarget(url.toString()); // } imagePart.getRelLast().setTarget(url.toString()); imagePart.setImageInfo(info); return imagePart; }
/** * Create an image part from the provided filePath image, attach it to the source part (eg the * main document part, a header part etc), and return it. * * <p>Works for both docx and pptx. * * @param opcPackage * @param sourcePart * @param filePath * @return * @throws Exception */ public static BinaryPartAbstractImage createImagePart( OpcPackage opcPackage, Part sourcePart, File imageFile) throws Exception { final byte[] locByte = new byte[1]; // We are in the case that image is not load (no byte Array) so isLoad is false ImageInfo info = ensureFormatIsSupported(imageFile, locByte, false); ContentTypeManager ctm = opcPackage.getContentTypeManager(); // Ensure the relationships part exists if (sourcePart.getRelationshipsPart() == null) { RelationshipsPart.createRelationshipsPartForPart(sourcePart); } String proposedRelId = sourcePart.getRelationshipsPart().getNextId(); String ext = info.getMimeType().substring(info.getMimeType().indexOf("/") + 1); BinaryPartAbstractImage imagePart = (BinaryPartAbstractImage) ctm.newPartForContentType( info.getMimeType(), createImageName(opcPackage, sourcePart, proposedRelId, ext), null); log.debug( "created part " + imagePart.getClass().getName() + " with name " + imagePart.getPartName().toString()); FileInputStream fis = new FileInputStream(imageFile); imagePart.setBinaryData(fis); imagePart.rels.add(sourcePart.addTargetPart(imagePart, proposedRelId)); imagePart.setImageInfo(info); return imagePart; }
/** * Create an image part from the provided byte array, attach it to the source part (eg the main * document part, a header part etc), and return it. * * <p>Works for both docx and pptx. * * <p>Note: this method creates a temp file (and attempts to delete it). That's because it uses * org.apache.xmlgraphics * * @param opcPackage * @param sourcePart * @param bytes * @return * @throws Exception */ public static BinaryPartAbstractImage createImagePart( OpcPackage opcPackage, Part sourcePart, byte[] bytes) throws Exception { // Whatever image type this is, we're going to need // to know its dimensions. // For that we use ImageInfo, which can only // load an image from a URI. // So first, write the bytes to a temp file File tmpImageFile = File.createTempFile("img", ".img"); FileOutputStream fos = new FileOutputStream(tmpImageFile); fos.write(bytes); fos.close(); log.debug("created tmp file: " + tmpImageFile.getAbsolutePath()); ImageInfo info = ensureFormatIsSupported(tmpImageFile, bytes, true); // In the absence of an exception, tmpImageFile now contains an image // Word will accept ContentTypeManager ctm = opcPackage.getContentTypeManager(); // Ensure the relationships part exists if (sourcePart.getRelationshipsPart() == null) { RelationshipsPart.createRelationshipsPartForPart(sourcePart); } String proposedRelId = sourcePart.getRelationshipsPart().getNextId(); String ext = info.getMimeType().substring(info.getMimeType().indexOf("/") + 1); // System.out.println(ext); BinaryPartAbstractImage imagePart = (BinaryPartAbstractImage) ctm.newPartForContentType( info.getMimeType(), createImageName(opcPackage, sourcePart, proposedRelId, ext), null); log.debug( "created part " + imagePart.getClass().getName() + " with name " + imagePart.getPartName().toString()); FileInputStream fis = new FileInputStream(tmpImageFile); imagePart.setBinaryData(fis); imagePart.rels.add(sourcePart.addTargetPart(imagePart, proposedRelId)); imagePart.setImageInfo(info); // Delete the tmp file // As per http://stackoverflow.com/questions/991489/i-cant-delete-a-file-in-java // the following 3 lines are necessary, at least on Win 7 x64 // Also reported on Win XP, but in my testing, the files were deleting OK anyway. fos = null; fis = null; if (Docx4jProperties.getProperty( "docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage.TempFiles.ForceGC", true)) { System.gc(); } if (tmpImageFile.delete()) { log.debug(".. deleted " + tmpImageFile.getAbsolutePath()); } else { log.warn("Couldn't delete tmp file " + tmpImageFile.getAbsolutePath()); tmpImageFile.deleteOnExit(); // If that doesn't work, see "Clean Up Your Mess: Managing Temp Files in Java Apps" // at devx.com } return imagePart; }