How to zip and base64 an org.w3c.dom.Document - java

I have a org.w3c.dom.Document and have to zip and base64 encode it to send it with the EBICS protocol via HTTP/HTTPS
I tried
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
Source xmlSource = new DOMSource(doc);
Result outputTarget = new StreamResult(outputStream);
TransformerFactory.newInstance().newTransformer().transform(xmlSource, outputTarget);
InputStream inflated_stream = new InflaterInputStream(new ByteArrayInputStream(outputStream.toByteArray()));
final byte[] bytes64bytes = Base64.encodeBase64(IOUtils.toByteArray(inflated_stream));
OrderData = new String(bytes64bytes);
but get an exception
java.util.zip.ZipException: incorrect header check
at java.util.zip.InflaterInputStream.read(InflaterInputStream.java:164)
at java.io.FilterInputStream.read(FilterInputStream.java:107)
at org.apache.commons.io.IOUtils.copyLarge(IOUtils.java:1025)
at org.apache.commons.io.IOUtils.copy(IOUtils.java:999)
at org.apache.commons.io.IOUtils.toByteArray(IOUtils.java:218)

I haven't tried this, but wouldn't the following do what you need?
OutputStream outputStream = new ZipOutputStream(new ByteArrayOutputStream());
I think your problem might be down to the use of InflaterInputStream - aren't you trying to deflate this stream? You code may work if you just change InflaterInputStream to DeflaterInputStream

Changing
InputStream inflated_stream = new InflaterInputStream(new ByteArrayInputStream(outputStream.toByteArray()));
to
InputStream inflated_stream = new DeflaterInputStream(new ByteArrayInputStream(outputStream.toByteArray()));
solved the issue
Thanks

Related

Read the binary image data from a URL into a ByteArrayInputStream from HttpUrlConnect::URL

I'm trying to pull the image from a URL and read it directly into a ByteArrayInputStream. I found one way of doing it, but it requires an image type, and there will be various image types, so I'd like to find a simple way to just read the binary data right in.
Here is my latest attempt. I'm using a BufferedImage, which I don't think is necessary.
URL url = new URL("http://hobbylesson.com/wp-content/uploads/2015/04/Simple-Acrylic-Painting-Ideas00005.jpg");
//Read in the image
BufferedImage image = ImageIO.read(url);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(image, "png", baos);
is = new ByteArrayInputStream(baos.toByteArray());
URL url = new URL("http://hobbylesson.com/wp-content/uploads/2015/04/Simple-Acrylic-Painting-Ideas00005.jpg");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
url.openStream().transferTo(baos);
ByteArrayInputStream in = new ByteArrayInputStream(baos.toByteArray());
The transferTo() method exists since Java 9. If you should use an older version of Java please see here for an alternative. Main drawback of this solution is that it has to read the whole file into memory first. If you anyway plan to forward the binary data to an other process you could omit the ByteArray streams and transfer the content directly to an OutputStream.
As an alternative to the solution proposed by #rmunge, the Apache Commons IO library provides the class IOUtils which can be vey useful in your use case.
If you are using Maven for instance, you can import the library including the following dependency in your pom.xml:
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.8.0</version>
</dependency>
Then, you can use IOUtils like this:
URL url = new URL("http://hobbylesson.com/wp-content/uploads/2015/04/Simple-Acrylic-Painting-Ideas00005.jpg");
try (
InputStream imageInputStream = url.openStream();
ByteArrayOutputStream bOut = new ByteArrayOutputStream()
) {
// You can obtain a byte[] as well if required
// Please, consider write to the actual final OutputStream instead
// of into the intermediate byte array output stream to optimize memory
// consumption
IOUtils.copy(imageInputStream, bOut);
// Create an input stream from the read bytes
ByteArrayInputStream in = new ByteArrayInputStream(bOut.toByteArray());
// ...
} catch (IOException ioe) {
ioe.printStackTrace();
}
Or simply this approach:
URL url = new URL("http://hobbylesson.com/wp-content/uploads/2015/04/Simple-Acrylic-Painting-Ideas00005.jpg");
byte[] imageBytes = IOUtils.toByteArray(url);
ByteArrayInputStream in = new ByteArrayInputStream(imageBytes);
For your comments, if the problem if you are trying to avoid network latency problems, if the requirement for a ByteArrayInputStream is not strictly necessary, as you can see in the javadocs perhaps the following code may be helpful as well:
URL url = new URL("http://hobbylesson.com/wp-content/uploads/2015/04/Simple-Acrylic-Painting-Ideas00005.jpg");
try (InputStream imageInputStream = url.openStream()) {
InputStream in = IOUtils.toBufferedInputStream(imageInputStream);
//...
}
Of course, you can always perform the read and write "manually" using the standard Java InputStream and OutputStream mechanisms:
URL url = new URL("http://hobbylesson.com/wp-content/uploads/2015/04/Simple-Acrylic-Painting-Ideas00005.jpg");
try (
InputStream inputStream = url.openStream();
BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream);
) {
byte[] buffer = new byte[8192];
int bytesRead;
while ((bytesRead = bufferedInputStream.read(buffer)) != -1) {
bufferedOutputStream.write(buffer, 0, bytesRead);
}
bufferedOutputStream.flush();
// Create an input stream from the read bytes
ByteArrayInputStream in = new ByteArrayInputStream(outputStream.toByteArray());
// ...
} catch (IOException ioe) {
ioe.printStackTrace();
}
If you require more control about the underlying URL connection you can use URLConnection or HttpURLConnection, or many HTTP client libraries like Apache HttpClient or OkHttp, to name some of them.
Take as example the problem pointed out by #LuisCarlos in his comment, in order to avoid possible leak connections:
URLConnection urlConn = null;
try {
urlConn = url.openConnection();
urlConn.setConnectTimeout(5000);
urlConn.setReadTimeout(30000);
InputStream inputStream = urlConn.getInputStream();
// the rest of the code...
} catch (Exception e) {
}
If you need to detect the actual image type consider the use of Tika or JMimeMagic.
Here's the solution I found to work. Thanks for the two approaches above. I'd rather avoid external libraries, but because the environment is a real pain. Similar, I should have access to Java 9 and transferTo(), but that's not working.
This answerer was also helpful: Convert InputStream(Image) to ByteArrayInputStream
URL url = new URL("http://hobbylesson.com/wp-content/uploads/2015/04/Simple-Acrylic-Painting-Ideas00005.jpg");
InputStream source = url.openStream();
byte[] buf = new byte[8192];
int bytesRead = 0;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
while((bytesRead = source.read(buf)) != -1) {
baos.write(buf, 0, bytesRead);
}
is = new ByteArrayInputStream(baos.toByteArray());

Saving Base64 String to file

I am getting a JSON response from webservice call as
]1
I have to save this file to my system. I am using the following code:
BASE64Decoder decoder = new BASE64Decoder();
byte[] decodedBytes = decoder.decodeBuffer(response);
ByteArrayInputStream bis = new ByteArrayInputStream(decodedBytes);
bis.close();
File file = new File("C:/image one.jpeg");
FileOutputStream fop = new FileOutputStream(file);
fop.write(decodedBytes);
fop.flush();
fop.close();
The file gets saved but is corrupt and can't be opened. Can anybody shed some light on what I am doing wrong?
Try to use Base64 class from java.util.Base64
byte[] decodedBytes = Base64.getDecoder().decode(base64String);
Or Base64 from org.apache.commons.codec.binary
byte[] decodedBytes = Base64.decodeBase64(base64String);
And you won't need ByteArrayInputStream object
See this link for more detailed answer

XML External Entity Injection: Hp Fortify issue in java 1.6

I was trying to fix XEE issue and have tried other options but won't work. Would be great if there were any pointers.
Below is my code snippet..
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
Source xmlSource = new DOMSource(feed);
Result outputTarget = new StreamResult(outputStream);
TransformerFactory.newInstance().newTransformer().transform(xmlSource,outputTarget);
is = new ByteArrayInputStream(outputStream.toByteArray());
Have a look at OWASP XXE Prevention Cheat Sheet
based of what i see in your code, you should modifiy it like this :
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
Source xmlSource = new DOMSource(feed);
Result outputTarget = new StreamResult(outputStream);
TransformerFactory tf = TransformerFactory.newInstance();
tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
tf.newTransformer().transform(xmlSource,outputTarget);
is = new ByteArrayInputStream(outputStream.toByteArray());

PDFBox document to InputStream

I'm trying to take a PDDocument object and pass it to other module as InputStream without saving the document to the file system.
Now, I read about PDStream and kind of understood the purpose of this. Hence, I tried to do something like this:
PDStream stream = new PDStream(document);
InputStream is = stream.createInputStream();
But when I try to load that input stream into a PDDocument, I get this error:
Exception in thread "main" java.io.IOException: Error: End-of-File, expected line
at org.apache.pdfbox.pdfparser.BaseParser.readLine(BaseParser.java:1111)
at org.apache.pdfbox.pdfparser.COSParser.parseHeader(COSParser.java:1885)
at org.apache.pdfbox.pdfparser.COSParser.parsePDFHeader(COSParser.java:1868)
at org.apache.pdfbox.pdfparser.PDFParser.parse(PDFParser.java:245)
at org.apache.pdfbox.pdmodel.PDDocument.load(PDDocument.java:1098)
at org.apache.pdfbox.pdmodel.PDDocument.load(PDDocument.java:995)
at app.DGDCreator.main(DGDCreator.java:35)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:143)
Later I discovered that the result file is 0kb in size...
So anyone else searching can have a good answer to this. I ran into this same situation where I didn't want to have to save the file to any machine and just handle the stream itself. I found an answer here and will repeat it below.
ByteArrayOutputStream out = new ByteArrayOutputStream();
pdDoc.save(out);
pdDoc.close();
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
I couldn't understand why you want to do this but, following code will do it:
public static void main(String[] args) throws IOException {
byte[] file = FileUtils.readFileToByteArray(new File(
"C:\\temp\\a_file.pdf"));
PDDocument document = null;
InputStream is = null;
ByteArrayOutputStream out = null;
try {
document = PDDocument.load(file);
out = new ByteArrayOutputStream();
document.save(out);
byte[] data = out.toByteArray();
is = new ByteArrayInputStream(data);
FileUtils.writeByteArrayToFile(new File(
"C:\\temp\\denemeTEST123.pdf"), IOUtils.toByteArray(is));
} finally {
IOUtils.closeQuietly(out);
IOUtils.closeQuietly(is);
IOUtils.closeQuietly(document);
}
}

how to create an InputStream from a Document or Node

How can I create an InputStream object from a XML Document or Node object to be used in xstream? I need to replace the ??? with some meaningful code. Thanks.
Document doc = getDocument();
InputStream is = ???;
MyObject obj = (MyObject) xstream.fromXML(is);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
Source xmlSource = new DOMSource(doc);
Result outputTarget = new StreamResult(outputStream);
TransformerFactory.newInstance().newTransformer().transform(xmlSource, outputTarget);
InputStream is = new ByteArrayInputStream(outputStream.toByteArray());
If you are using Java without any Third Party Libraries, you can create InputStream using below code:
/*
* Convert a w3c dom node to a InputStream
*/
private InputStream nodeToInputStream(Node node) throws TransformerException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
Result outputTarget = new StreamResult(outputStream);
Transformer t = TransformerFactory.newInstance().newTransformer();
t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
t.transform(new DOMSource(node), outputTarget);
return new ByteArrayInputStream(outputStream.toByteArray());
}
One way to do it: Adapt the Document to a Source with DOMSource. Create a StreamResult to adapt a ByteArrayOutputStream. Use a Transformer from TransformerFactory.newTransformer to copy across the data. Retrieve your byte[] and stream with ByteArrayInputStream.
Putting the code together is left as an exercise.
public static InputStream document2InputStream(Document document) throws IOException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
OutputFormat outputFormat = new OutputFormat(document);
XMLSerializer serializer = new XMLSerializer(outputStream, outputFormat);
serializer.serialize(document);
return new ByteArrayInputStream(outputStream.toByteArray());
}
This works if you are using apache Xerces implementation, you can also set format parameter with the output format.
public static InputStream documentToPrettyInputStream(Document doc) throws IOException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
XMLWriter xmlWriter = new XMLWriter(outputStream, OutputFormat.createPrettyPrint());
xmlWriter.write(doc);
xmlWriter.close();
InputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
return inputStream;
}
If you happen to use DOM4j and you need to print it pretty!

Categories

Resources