diff options
| author | Michael Williamson <mike@zwobble.org> | 2016-02-13 23:32:26 +0000 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2016-02-13 23:32:26 +0000 |
| commit | c46ec78de9524a7b7df0b475b1447a83b4f857fe (patch) | |
| tree | c98c58f6d4aa8cde8824bbfe3b73131143f1d3cc /src | |
| parent | 6dd319ca5eebe1f97b9558b5b45bbccf402eb319 (diff) | |
Read linked blips
Diffstat (limited to 'src')
6 files changed, 88 insertions, 7 deletions
diff --git a/src/main/java/org/zwobble/mammoth/Mammoth.java b/src/main/java/org/zwobble/mammoth/Mammoth.java index 0651944..63a313f 100644 --- a/src/main/java/org/zwobble/mammoth/Mammoth.java +++ b/src/main/java/org/zwobble/mammoth/Mammoth.java @@ -8,6 +8,7 @@ import org.zwobble.mammoth.xml.XmlElement; import java.io.File; import java.io.IOException; +import java.io.InputStream; import java.util.zip.ZipFile; import static com.google.common.collect.Iterables.transform; @@ -21,12 +22,19 @@ public class Mammoth { Numbering numbering = Numbering.EMPTY; Relationships relationships = Relationships.EMPTY; ContentTypes contentTypes = ContentTypes.DEFAULT; + FileReader fileReader = new FileReader() { + @Override + public InputStream getInputStream(String uri) throws IOException { + throw new UnsupportedOperationException(); + } + }; DocumentXmlReader reader = new DocumentXmlReader(new BodyXmlReader( styles, numbering, relationships, contentTypes, - zipFile)); + zipFile, + fileReader)); return reader.readElement(documentXml) .map(Mammoth::convertToHtml); } catch (IOException e) { diff --git a/src/main/java/org/zwobble/mammoth/docx/BodyXmlReader.java b/src/main/java/org/zwobble/mammoth/docx/BodyXmlReader.java index e911a63..0d49809 100644 --- a/src/main/java/org/zwobble/mammoth/docx/BodyXmlReader.java +++ b/src/main/java/org/zwobble/mammoth/docx/BodyXmlReader.java @@ -27,25 +27,27 @@ public class BodyXmlReader { private static final Set<String> IMAGE_TYPES_SUPPORTED_BY_BROWSERS = ImmutableSet.of( "image/png", "image/gif", "image/jpeg", "image/svg+xml", "image/tiff"); - private final Styles styles; private final Numbering numbering; private final Relationships relationships; private final ContentTypes contentTypes; private final DocxFile file; + private final FileReader fileReader; public BodyXmlReader( Styles styles, Numbering numbering, Relationships relationships, ContentTypes contentTypes, - DocxFile file) + DocxFile file, + FileReader fileReader) { this.styles = styles; this.numbering = numbering; this.relationships = relationships; this.contentTypes = contentTypes; this.file = file; + this.fileReader = fileReader; } public ReadResult readElement(XmlElement element) { @@ -276,9 +278,18 @@ public class BodyXmlReader { } private ReadResult readBlip(XmlElement blip, Optional<String> altText) { - String relationshipId = blip.getAttribute("r:embed"); - String imagePath = relationshipIdToDocxPath(relationshipId); - return readImage(imagePath, altText, () -> file.getInputStream(imagePath)); + Optional<String> embedRelationshipId = blip.getAttributeOrNone("r:embed"); + Optional<String> linkRelationshipId = blip.getAttributeOrNone("r:link"); + if (embedRelationshipId.isPresent()) { + String imagePath = relationshipIdToDocxPath(embedRelationshipId.get()); + return readImage(imagePath, altText, () -> file.getInputStream(imagePath)); + } else if (linkRelationshipId.isPresent()) { + String imagePath = relationships.findRelationshipById(linkRelationshipId.get()).getTarget(); + return readImage(imagePath, altText, () -> fileReader.getInputStream(imagePath)); + } else { + // TODO: emit warning + return ReadResult.EMPTY_SUCCESS; + } } private ReadResult readImage(String imagePath, Optional<String> altText, InputStreamSupplier open) { diff --git a/src/main/java/org/zwobble/mammoth/docx/FileReader.java b/src/main/java/org/zwobble/mammoth/docx/FileReader.java new file mode 100644 index 0000000..9bb5b25 --- /dev/null +++ b/src/main/java/org/zwobble/mammoth/docx/FileReader.java @@ -0,0 +1,8 @@ +package org.zwobble.mammoth.docx; + +import java.io.IOException; +import java.io.InputStream; + +public interface FileReader { + InputStream getInputStream(String uri) throws IOException; +} diff --git a/src/test/java/org/zwobble/mammoth/tests/docx/BodyXmlReaderMakers.java b/src/test/java/org/zwobble/mammoth/tests/docx/BodyXmlReaderMakers.java index 41cefd5..f19f505 100644 --- a/src/test/java/org/zwobble/mammoth/tests/docx/BodyXmlReaderMakers.java +++ b/src/test/java/org/zwobble/mammoth/tests/docx/BodyXmlReaderMakers.java @@ -15,6 +15,7 @@ public class BodyXmlReaderMakers { public static final Property<BodyXmlReader, Relationships> RELATIONSHIPS = newProperty(); public static final Property<BodyXmlReader, ContentTypes> CONTENT_TYPES = newProperty(); public static final Property<BodyXmlReader, DocxFile> DOCX_FILE = newProperty(); + public static final Property<BodyXmlReader, FileReader> FILE_READER = newProperty(); public static final Instantiator<BodyXmlReader> bodyReader = propertyLookup -> new BodyXmlReader( @@ -31,5 +32,11 @@ public class BodyXmlReaderMakers { @Override public void close() throws IOException { } + }), + propertyLookup.valueOf(FILE_READER, new FileReader() { + @Override + public InputStream getInputStream(String uri) throws IOException { + throw new UnsupportedOperationException(); + } })); } diff --git a/src/test/java/org/zwobble/mammoth/tests/docx/BodyXmlTests.java b/src/test/java/org/zwobble/mammoth/tests/docx/BodyXmlTests.java index 49542ec..5c4c40d 100644 --- a/src/test/java/org/zwobble/mammoth/tests/docx/BodyXmlTests.java +++ b/src/test/java/org/zwobble/mammoth/tests/docx/BodyXmlTests.java @@ -419,7 +419,7 @@ public class BodyXmlTests { hasProperty("contentType", deepEquals(Optional.of("image/png"))))); assertThat( CharStreams.toString(new InputStreamReader(image.open())), - equalTo("Not an image at all!")); + equalTo(imageBytes)); } private class EmbeddedImage { @@ -446,11 +446,30 @@ public class BodyXmlTests { with(DOCX_FILE, file), with(CONTENT_TYPES, contentTypes)), element); + assertThat( result, hasProperty("warnings", deepEquals(list(warning("Image of type image/x-emf is unlikely to display in web browsers"))))); } + @Test + public void canReadLinkedPictures() throws IOException { + XmlElement element = inlineImageXml(linkedBlipXml("rId5"), ""); + Relationships relationships = new Relationships(map( + "rId5", new Relationship("file:///media/hat.png"))); + String imageBytes = "Not an image at all!"; + + Image image = (Image) readSuccess( + a(bodyReader, + with(RELATIONSHIPS, relationships), + with(FILE_READER, new InMemoryFileReader(map("file:///media/hat.png", imageBytes)))), + element); + + assertThat( + CharStreams.toString(new InputStreamReader(image.open())), + equalTo(imageBytes)); + } + private XmlElement inlineImageXml(XmlElement blip, String description) { return element("w:drawing", list( element("wp:inline", imageXml(blip, description)))); @@ -474,6 +493,10 @@ public class BodyXmlTests { return blipXml(map("r:embed", relationshipId)); } + private XmlElement linkedBlipXml(String relationshipId) { + return blipXml(map("r:link", relationshipId)); + } + private XmlElement blipXml(Map<String, String> attributes) { return element("a:blip", attributes); } diff --git a/src/test/java/org/zwobble/mammoth/tests/docx/InMemoryFileReader.java b/src/test/java/org/zwobble/mammoth/tests/docx/InMemoryFileReader.java new file mode 100644 index 0000000..7b716cc --- /dev/null +++ b/src/test/java/org/zwobble/mammoth/tests/docx/InMemoryFileReader.java @@ -0,0 +1,24 @@ +package org.zwobble.mammoth.tests.docx; + +import org.zwobble.mammoth.docx.FileReader; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.Map; +import java.util.Optional; + +public class InMemoryFileReader implements FileReader { + private final Map<String, String> entries; + + public InMemoryFileReader(Map<String, String> entries) { + this.entries = entries; + } + + @Override + public InputStream getInputStream(String name) throws IOException { + String value = Optional.ofNullable(entries.get(name)).get(); + return new ByteArrayInputStream(value.getBytes(StandardCharsets.UTF_8)); + } +} |
