aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNick Burch <nick@apache.org>2016-06-21 14:27:41 +0000
committerNick Burch <nick@apache.org>2016-06-21 14:27:41 +0000
commit02ca37ca183f2deb63763e993d3a49e755073e26 (patch)
tree188efa955ff86723ddbe6dfbced34e747af07961
parent8100b33ead773cde1d8f85084e82652d14f524bd (diff)
downloadpoi-02ca37ca183f2deb63763e993d3a49e755073e26.tar.gz
poi-02ca37ca183f2deb63763e993d3a49e755073e26.zip
#59717 POIXMLProperties helper methods for reading and changing OOXML document thumbnails
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1749528 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--src/ooxml/java/org/apache/poi/POIXMLProperties.java71
-rw-r--r--src/ooxml/java/org/apache/poi/openxml4j/opc/OPCPackage.java40
-rw-r--r--src/ooxml/testcases/org/apache/poi/TestPOIXMLProperties.java36
3 files changed, 130 insertions, 17 deletions
diff --git a/src/ooxml/java/org/apache/poi/POIXMLProperties.java b/src/ooxml/java/org/apache/poi/POIXMLProperties.java
index f55788de1a..0ce6ad6774 100644
--- a/src/ooxml/java/org/apache/poi/POIXMLProperties.java
+++ b/src/ooxml/java/org/apache/poi/POIXMLProperties.java
@@ -19,17 +19,20 @@ package org.apache.poi;
import static org.apache.poi.POIXMLTypeLoader.DEFAULT_XML_OPTIONS;
import java.io.IOException;
+import java.io.InputStream;
import java.io.OutputStream;
import java.util.Date;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
+import org.apache.poi.openxml4j.opc.ContentTypes;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackagePartName;
import org.apache.poi.openxml4j.opc.PackageRelationshipCollection;
import org.apache.poi.openxml4j.opc.PackageRelationshipTypes;
import org.apache.poi.openxml4j.opc.PackagingURIHelper;
+import org.apache.poi.openxml4j.opc.StreamHelper;
import org.apache.poi.openxml4j.opc.TargetMode;
import org.apache.poi.openxml4j.opc.internal.PackagePropertiesPart;
import org.apache.poi.openxml4j.util.Nullable;
@@ -37,8 +40,9 @@ import org.apache.xmlbeans.XmlException;
import org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperty;
/**
- * Wrapper around the two different kinds of OOXML properties
- * a document can have
+ * Wrapper around the three different kinds of OOXML properties
+ * and metadata a document can have (Core, Extended and Custom),
+ * as well Thumbnails.
*/
public class POIXMLProperties {
private OPCPackage pkg;
@@ -121,6 +125,69 @@ public class POIXMLProperties {
public CustomProperties getCustomProperties() {
return cust;
}
+
+ /**
+ * Returns the {@link PackagePart} for the Document
+ * Thumbnail, or <code>null</code> if there isn't one
+ *
+ * @return The Document Thumbnail part or null
+ */
+ protected PackagePart getThumbnailPart() {
+ PackageRelationshipCollection rels =
+ pkg.getRelationshipsByType(PackageRelationshipTypes.THUMBNAIL);
+ if(rels.size() == 1) {
+ return pkg.getPart(rels.getRelationship(0));
+ }
+ return null;
+ }
+ /**
+ * Returns the name of the Document thumbnail, eg
+ * <code>thumbnail.jpeg</code>, or <code>null</code> if there
+ * isn't one.
+ *
+ * @return The thumbnail filename, or null
+ */
+ public String getThumbnailFilename() {
+ PackagePart tPart = getThumbnailPart();
+ if (tPart == null) return null;
+ String name = tPart.getPartName().getName();
+ return name.substring(name.lastIndexOf('/'));
+ }
+ /**
+ * Returns the Document thumbnail image data, or
+ * <code>null</code> if there isn't one.
+ *
+ * @return The thumbnail data, or null
+ */
+ public InputStream getThumbnailImage() throws IOException {
+ PackagePart tPart = getThumbnailPart();
+ if (tPart == null) return null;
+ return tPart.getInputStream();
+ }
+
+ /**
+ * Sets the Thumbnail for the document, replacing any existing
+ * one.
+ *
+ * @param name The filename for the thumbnail image, eg <code>thumbnail.jpg</code>
+ * @param imageData The inputstream to read the thumbnail image from
+ */
+ public void setThumbnail(String filename, InputStream imageData) throws IOException {
+ PackagePart tPart = getThumbnailPart();
+ if (tPart == null) {
+ // New thumbnail
+ pkg.addThumbnail(filename, imageData);
+ } else {
+ // Change existing
+ String newType = ContentTypes.getContentTypeFromFileExtension(filename);
+ if (! newType.equals(tPart.getContentType())) {
+ throw new IllegalArgumentException("Can't set a Thumbnail of type " +
+ newType + " when existing one is of a different type " +
+ tPart.getContentType());
+ }
+ StreamHelper.copyStream(imageData, tPart.getOutputStream());
+ }
+ }
/**
* Commit changes to the underlying OPC package
diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/OPCPackage.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/OPCPackage.java
index e84d83e3e6..e70496f3f4 100644
--- a/src/ooxml/java/org/apache/poi/openxml4j/opc/OPCPackage.java
+++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/OPCPackage.java
@@ -474,19 +474,32 @@ public abstract class OPCPackage implements RelationshipSource, Closeable {
* the addition of a thumbnail in a package. You can do the same work by
* using the traditionnal relationship and part mechanism.
*
- * @param path
- * The full path to the image file.
+ * @param path The full path to the image file.
*/
public void addThumbnail(String path) throws IOException {
+ // Check parameter
+ if (path == null || path.isEmpty()) {
+ throw new IllegalArgumentException("path");
+ }
+ String name = path.substring(path.lastIndexOf(File.separatorChar) + 1);
+
+ FileInputStream is = new FileInputStream(path);
+ addThumbnail(name, is);
+ is.close();
+ }
+ /**
+ * Add a thumbnail to the package. This method is provided to make easier
+ * the addition of a thumbnail in a package. You can do the same work by
+ * using the traditionnal relationship and part mechanism.
+ *
+ * @param path The full path to the image file.
+ */
+ public void addThumbnail(String filename, InputStream data) throws IOException {
// Check parameter
- if ("".equals(path)) {
- throw new IllegalArgumentException("path");
+ if (filename == null || filename.isEmpty()) {
+ throw new IllegalArgumentException("filename");
}
- // Get the filename from the path
- String filename = path
- .substring(path.lastIndexOf(File.separatorChar) + 1);
-
// Create the thumbnail part name
String contentType = ContentTypes
.getContentTypeFromFileExtension(filename);
@@ -495,10 +508,10 @@ public abstract class OPCPackage implements RelationshipSource, Closeable {
thumbnailPartName = PackagingURIHelper.createPartName("/docProps/"
+ filename);
} catch (InvalidFormatException e) {
+ String partName = "/docProps/thumbnail" +
+ filename.substring(filename.lastIndexOf(".") + 1);
try {
- thumbnailPartName = PackagingURIHelper
- .createPartName("/docProps/thumbnail"
- + path.substring(path.lastIndexOf(".") + 1));
+ thumbnailPartName = PackagingURIHelper.createPartName(partName);
} catch (InvalidFormatException e2) {
throw new InvalidOperationException(
"Can't add a thumbnail file named '" + filename + "'", e2);
@@ -519,10 +532,7 @@ public abstract class OPCPackage implements RelationshipSource, Closeable {
PackageRelationshipTypes.THUMBNAIL);
// Copy file data to the newly created part
- FileInputStream is = new FileInputStream(path);
- StreamHelper.copyStream(is, thumbnailPart
- .getOutputStream());
- is.close();
+ StreamHelper.copyStream(data, thumbnailPart.getOutputStream());
}
/**
diff --git a/src/ooxml/testcases/org/apache/poi/TestPOIXMLProperties.java b/src/ooxml/testcases/org/apache/poi/TestPOIXMLProperties.java
index 1d9be8d1aa..0a34280154 100644
--- a/src/ooxml/testcases/org/apache/poi/TestPOIXMLProperties.java
+++ b/src/ooxml/testcases/org/apache/poi/TestPOIXMLProperties.java
@@ -19,9 +19,11 @@ package org.apache.poi;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.Calendar;
import java.util.Date;
@@ -42,12 +44,16 @@ import org.junit.Test;
*/
public final class TestPOIXMLProperties {
private XWPFDocument sampleDoc;
+ private XWPFDocument sampleNoThumb;
private POIXMLProperties _props;
private CoreProperties _coreProperties;
@Before
public void setUp() throws IOException {
sampleDoc = XWPFTestDataSamples.openSampleDocument("documentProperties.docx");
+ sampleNoThumb = XWPFTestDataSamples.openSampleDocument("SampleDoc.docx");
+ assertNotNull(sampleDoc);
+ assertNotNull(sampleNoThumb);
_props = sampleDoc.getProperties();
_coreProperties = _props.getCoreProperties();
assertNotNull(_props);
@@ -56,6 +62,7 @@ public final class TestPOIXMLProperties {
@After
public void closeResources() throws Exception {
sampleDoc.close();
+ sampleNoThumb.close();
}
@Test
@@ -214,6 +221,35 @@ public final class TestPOIXMLProperties {
return utcString.equals(dateTimeUtcString);
}
+
+ public void testThumbnails() throws Exception {
+ POIXMLProperties noThumbProps = sampleNoThumb.getProperties();
+
+ assertNotNull(_props.getThumbnailPart());
+ assertNull(noThumbProps.getThumbnailPart());
+
+ assertNotNull(_props.getThumbnailFilename());
+ assertNull(noThumbProps.getThumbnailFilename());
+
+ assertNotNull(_props.getThumbnailImage());
+ assertNull(noThumbProps.getThumbnailImage());
+
+ assertEquals("thumbnail.jpeg", _props.getThumbnailFilename());
+
+
+ // Adding / changing
+ noThumbProps.setThumbnail("Testing.png", new ByteArrayInputStream(new byte[1]));
+ assertNotNull(noThumbProps.getThumbnailPart());
+ assertEquals("Testing.png", noThumbProps.getThumbnailFilename());
+ assertNotNull(noThumbProps.getThumbnailImage());
+ assertEquals(1, noThumbProps.getThumbnailImage().available());
+
+ noThumbProps.setThumbnail("Testing2.png", new ByteArrayInputStream(new byte[2]));
+ assertNotNull(noThumbProps.getThumbnailPart());
+ assertEquals("Testing.png", noThumbProps.getThumbnailFilename());
+ assertNotNull(noThumbProps.getThumbnailImage());
+ assertEquals(2, noThumbProps.getThumbnailImage().available());
+ }
private static String zeroPad(long i) {
if (i >= 0 && i <=9) {