#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
This commit is contained in:
parent
fdb7c7d1ff
commit
631ca92c16
@ -19,17 +19,20 @@ package org.apache.poi;
|
|||||||
import static org.apache.poi.POIXMLTypeLoader.DEFAULT_XML_OPTIONS;
|
import static org.apache.poi.POIXMLTypeLoader.DEFAULT_XML_OPTIONS;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
|
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
|
||||||
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
|
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.OPCPackage;
|
||||||
import org.apache.poi.openxml4j.opc.PackagePart;
|
import org.apache.poi.openxml4j.opc.PackagePart;
|
||||||
import org.apache.poi.openxml4j.opc.PackagePartName;
|
import org.apache.poi.openxml4j.opc.PackagePartName;
|
||||||
import org.apache.poi.openxml4j.opc.PackageRelationshipCollection;
|
import org.apache.poi.openxml4j.opc.PackageRelationshipCollection;
|
||||||
import org.apache.poi.openxml4j.opc.PackageRelationshipTypes;
|
import org.apache.poi.openxml4j.opc.PackageRelationshipTypes;
|
||||||
import org.apache.poi.openxml4j.opc.PackagingURIHelper;
|
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.TargetMode;
|
||||||
import org.apache.poi.openxml4j.opc.internal.PackagePropertiesPart;
|
import org.apache.poi.openxml4j.opc.internal.PackagePropertiesPart;
|
||||||
import org.apache.poi.openxml4j.util.Nullable;
|
import org.apache.poi.openxml4j.util.Nullable;
|
||||||
@ -37,8 +40,9 @@ import org.apache.xmlbeans.XmlException;
|
|||||||
import org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperty;
|
import org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperty;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrapper around the two different kinds of OOXML properties
|
* Wrapper around the three different kinds of OOXML properties
|
||||||
* a document can have
|
* and metadata a document can have (Core, Extended and Custom),
|
||||||
|
* as well Thumbnails.
|
||||||
*/
|
*/
|
||||||
public class POIXMLProperties {
|
public class POIXMLProperties {
|
||||||
private OPCPackage pkg;
|
private OPCPackage pkg;
|
||||||
@ -121,6 +125,69 @@ public class POIXMLProperties {
|
|||||||
public CustomProperties getCustomProperties() {
|
public CustomProperties getCustomProperties() {
|
||||||
return cust;
|
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
|
* Commit changes to the underlying OPC package
|
||||||
|
@ -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
|
* the addition of a thumbnail in a package. You can do the same work by
|
||||||
* using the traditionnal relationship and part mechanism.
|
* using the traditionnal relationship and part mechanism.
|
||||||
*
|
*
|
||||||
* @param path
|
* @param path The full path to the image file.
|
||||||
* The full path to the image file.
|
|
||||||
*/
|
*/
|
||||||
public void addThumbnail(String path) throws IOException {
|
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
|
// Check parameter
|
||||||
if ("".equals(path)) {
|
if (filename == null || filename.isEmpty()) {
|
||||||
throw new IllegalArgumentException("path");
|
throw new IllegalArgumentException("filename");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the filename from the path
|
|
||||||
String filename = path
|
|
||||||
.substring(path.lastIndexOf(File.separatorChar) + 1);
|
|
||||||
|
|
||||||
// Create the thumbnail part name
|
// Create the thumbnail part name
|
||||||
String contentType = ContentTypes
|
String contentType = ContentTypes
|
||||||
.getContentTypeFromFileExtension(filename);
|
.getContentTypeFromFileExtension(filename);
|
||||||
@ -495,10 +508,10 @@ public abstract class OPCPackage implements RelationshipSource, Closeable {
|
|||||||
thumbnailPartName = PackagingURIHelper.createPartName("/docProps/"
|
thumbnailPartName = PackagingURIHelper.createPartName("/docProps/"
|
||||||
+ filename);
|
+ filename);
|
||||||
} catch (InvalidFormatException e) {
|
} catch (InvalidFormatException e) {
|
||||||
|
String partName = "/docProps/thumbnail" +
|
||||||
|
filename.substring(filename.lastIndexOf(".") + 1);
|
||||||
try {
|
try {
|
||||||
thumbnailPartName = PackagingURIHelper
|
thumbnailPartName = PackagingURIHelper.createPartName(partName);
|
||||||
.createPartName("/docProps/thumbnail"
|
|
||||||
+ path.substring(path.lastIndexOf(".") + 1));
|
|
||||||
} catch (InvalidFormatException e2) {
|
} catch (InvalidFormatException e2) {
|
||||||
throw new InvalidOperationException(
|
throw new InvalidOperationException(
|
||||||
"Can't add a thumbnail file named '" + filename + "'", e2);
|
"Can't add a thumbnail file named '" + filename + "'", e2);
|
||||||
@ -519,10 +532,7 @@ public abstract class OPCPackage implements RelationshipSource, Closeable {
|
|||||||
PackageRelationshipTypes.THUMBNAIL);
|
PackageRelationshipTypes.THUMBNAIL);
|
||||||
|
|
||||||
// Copy file data to the newly created part
|
// Copy file data to the newly created part
|
||||||
FileInputStream is = new FileInputStream(path);
|
StreamHelper.copyStream(data, thumbnailPart.getOutputStream());
|
||||||
StreamHelper.copyStream(is, thumbnailPart
|
|
||||||
.getOutputStream());
|
|
||||||
is.close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -19,9 +19,11 @@ package org.apache.poi;
|
|||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
@ -42,12 +44,16 @@ import org.junit.Test;
|
|||||||
*/
|
*/
|
||||||
public final class TestPOIXMLProperties {
|
public final class TestPOIXMLProperties {
|
||||||
private XWPFDocument sampleDoc;
|
private XWPFDocument sampleDoc;
|
||||||
|
private XWPFDocument sampleNoThumb;
|
||||||
private POIXMLProperties _props;
|
private POIXMLProperties _props;
|
||||||
private CoreProperties _coreProperties;
|
private CoreProperties _coreProperties;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws IOException {
|
public void setUp() throws IOException {
|
||||||
sampleDoc = XWPFTestDataSamples.openSampleDocument("documentProperties.docx");
|
sampleDoc = XWPFTestDataSamples.openSampleDocument("documentProperties.docx");
|
||||||
|
sampleNoThumb = XWPFTestDataSamples.openSampleDocument("SampleDoc.docx");
|
||||||
|
assertNotNull(sampleDoc);
|
||||||
|
assertNotNull(sampleNoThumb);
|
||||||
_props = sampleDoc.getProperties();
|
_props = sampleDoc.getProperties();
|
||||||
_coreProperties = _props.getCoreProperties();
|
_coreProperties = _props.getCoreProperties();
|
||||||
assertNotNull(_props);
|
assertNotNull(_props);
|
||||||
@ -56,6 +62,7 @@ public final class TestPOIXMLProperties {
|
|||||||
@After
|
@After
|
||||||
public void closeResources() throws Exception {
|
public void closeResources() throws Exception {
|
||||||
sampleDoc.close();
|
sampleDoc.close();
|
||||||
|
sampleNoThumb.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -214,6 +221,35 @@ public final class TestPOIXMLProperties {
|
|||||||
|
|
||||||
return utcString.equals(dateTimeUtcString);
|
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) {
|
private static String zeroPad(long i) {
|
||||||
if (i >= 0 && i <=9) {
|
if (i >= 0 && i <=9) {
|
||||||
|
Loading…
Reference in New Issue
Block a user