I would like to send OutputStream object, which has pdf data, as file to the webbrowser.
The code is as follows.
#RequestMapping(value="/issue", method=RequestMethod.POST)
public void issue(HttpServletResponse response, TimeStampIssueParam param) throws JsonGenerationException, JsonMappingException, IOException {
OutputStream pdfOuput = issue(input);
response.setContentType("application/pdf");
ServletOutputStream respOutput = response.getOutputStream();
....
}
The problem is I already have the outputstream, and I do not want to convert it to byte array.
Any comment would be appreciated.
You can't: you can only copy an InputStream to an OutputStream. Then, you'll can use: org.springframework.util.FileCopyUtils.copy(InputStream, OutputStream)
First, I would say it is wrong to say that the OutputStream has any data. A stream just lets the data through to some destination. Sometimes (SocketOutputStream) this destination may be on a completely different computer, and sometimes (ByteArrayOutputStream) it will be closely related to the stream and even obtainable through it. But this is a detail of a specific stream, not something you can count on from an arbitrary one.
So, not knowing exactly where the result of the issue method comes from it is hard to provide a solution, but a generic OutputStream is not what it should return.
Guessing that the method generates some PDF data and writes it somewhere via an OutputStream, then returns the stream:
If it creates a File and the stream happens to be a FileOutputStream, it should return the file, file path or a FileInputStream for the same file instead.
If it creates eg. a ByteArrayOutputStream, then you already have a byte array, and additionally this stream type has a writeTo method that can be used directly to write the data to the ServletOutputStream; issue just has to return the stream as the proper type not hiding it behind the general interface.
For other OutputStream types, well, it depends on what exactly they are.
Related
Is there any way to convert an OutputStream into an InputStream?
So the following would work
InputStream convertOStoIS(OutputStream os) {
}
I do not want to use any libraries, I read that there are some who are able to accomplish this with bytecode manipulation.
Edit
I want to be able to intersect a sink, to analyze the data or redirect the output. I want to place another OutputStream under the on given by some function and redirect the data into another input stream.
The related topics had a ByteArrayOutputStream or a PipedStream which is not the case in my question.
Related:
How to convert OutputStream to InputStream?
Most efficient way to create InputStream from OutputStream
Use a java.io.FilterOutputStream to wrap the existing OutputStream. By overriding the write() method you can intercept output and do whatever you want with it, either send it somewhere else, modify it, or discard it completely.
As to your second question, you cannot change the sink of an OutputStream after the fact, i.e. cause previously written data to "move" somewhere else, but using a FilterOutputStream you can intercept and redirect any data written after you wrap the original `OutputStream.
To answer my own question, yes you can build a redirect like this:
class OutInInputRedirect {
public final transient InputStream is;
public final transient OutputStream os;
public OutInInputRedirect() throws IOException {
this(1024);
}
public OutInInputRedirect(int size) throws IOException {
PipedInputStream is = new PipedInputStream(size);
PipedOutputStream os = new PipedOutputStream(is);
this.is = is;
this.os = os;
}
}
Just use the OutputStream as an replacement and the InputStream in those places you need, be awere that the closing of the OutputStream also closes the InputStream!
It is quite easy and works as expected. Either way you cannot change an already connected stream (without reflection).
I have the following use case:
read from service InputStream
go through the InputStream and replace some stuff, result is stored in OutputStream
now I need to go on working with an InputStream created from the OutputStream
This is the code I use right now:
InputStream resourceStream = service.getStream();
ByteArrayOutputStream output = new ByteArrayOutputStream();
replace(resourceStream, output, ...);
resourceStream.close();
resourceStream = new ByteArrayInputStream(out.toByteArray());
A lot of shifting and converting streams, so I was wondering if there is a cleaner solution. Maybe some OutputStream which can be used as InputStream, or an OutputStream which contains an InputStream where the content is written to.
No matter how good your idea of having a single object to write and read data from, the implementations of InputStream and OutputStream have been made as "Classes" and not "Interfaces".
Also, due to the fact that, in Java, a single subclass cannot extend multiple Super Classes, the dream of having both Input and Output stream operations in a single class remains just a dream.
That said, the only other option left for programmers would be to create a class that has both InputStream and OutputStream exposed to its clients. Something similar to what as java.net.Socket does. It exposes a getInputStream and a getOutputStream which at a logical level reads from and writes to the same "socket".
So, you can do something like this:
public class IOStreamWrapper {
byte[] streamData;
public InputStream getInputStream() {
// return an inputstream that reads from streamData[]
}
public OutputStream getOutputStream() {
// return an outputstream that writes to streamData[]
}
}
References:
Java InputStream
Java OutputStream
Hope this helps!
I have a zip file and after decoding it I get a byte array now I want to create a FileInputStream object with that byte[] object. I dont want to create a file instead pass data content do FileInputStream.
Is there any way ?
following is the code:
byte[] decodedHeaderFileZip = decodeHeaderZipFile(headerExportFile);
FileInputStream fileInputStream = new FileInputStream(decodedHeaderZipFileString);
EDIT:
I wanted to build a ZipInputStream object with a FileInputStream.
I have a zip file and after decoding it I get a byte array now I want to create a FileInputStream object with that byte[] object.
But you don't have a file. You have some data in memory. So a FileInputStream is inappropriate - there's no file for it to read from.
If possible, use a ByteArrayInputStream instead:
InputStream input = new ByteArrayInputStream(decodedHeaderFileZip);
Where possible, express your API in terms of InputStream, Reader etc rather than any specific implementation - that allows you to be flexible in which implementation you use. (What I mean is that where possible, make method parameters and return types InputStream rather than FileInputStream - so that callers don't need to provide the specific types.)
If you absolutely have to create a FileInputStream, you'll need to write the data to a file first.
I have a library function as follows:
public static InputStream getResource(String url) throws MalformedURLException,
IOException {
return new URL(url).openConnection().getInputStream();
}
What would be the best way to add logging to this method to record the actual url response. Will I have to read the InputStream and then reset it?
(You can assume that I just want to print the results to the console for the sake of this example.)
If you would use a logger library and requests are small, then you could read whole InputStream into memory (e.g. into ByteArrayOutputStream), then log it, then construct ByteArrayInputStream as the method result.
If requests are big, you should dump it somewhere into a file or into a database blob. You could subclass the FilterInputStream and dump the data flow.
You cannot reset http stream in most cases.
You might copy the contents of the stream to a byte array, using a ByteArrayOutputStream, log the content of the byte array, and then return a ByteArrayInputStream constructed from the byte array. This puts the whole contents in memory, though.
We have a requirement to determine whether an incoming InputStream is a reference to an zip file or zip data. We do not have reference to the underlying source of the stream. We aim to copy the contents of this stream into an OutputStream directed at an alternate location.
I tried reading the stream using ZipInputStream and extracting a ZipEntry. The ZipEntry is null if the stream is a regular file - as expected - however, in checking for a ZipEntry I loose the initial couple of bytes from the stream. Hence, by the time I know that the stream is a regular stream, I have already lost initial data from the stream.
Any thoughts around how to check if the InputStream is an archive without data loss would be helpful.
Thanks.
Assuming your original inputstream is not buffered, I would try wrapping the original stream in a BufferedInputStream, before wrapping that in a ZipInputStream to check. You can use "mark" and "reset" in the BufferedInputStream to return to the initial position in the stream, after your check.
This is how I did it.
Using mark/reset to restore the stream if the GZIPInputStream detects incorrect zip format (throws the ZipException).
/**
* Wraps the input stream with GZIPInputStream if needed.
* #param inputStream
* #return
* #throws IOException
*/
private InputStream wrapIfZip(InputStream inputStream) throws IOException {
if (!inputStream.markSupported()) {
inputStream = new BufferedInputStream(inputStream);
}
inputStream.mark(1000);
try {
return new GZIPInputStream(inputStream);
} catch (ZipException e) {
inputStream.reset();
return inputStream;
}
}
You can check first bytes of stream for ZIP local header signature (PK 0x03 0x04), that would be enough for most cases. If you need more precision, you should take last ~100 bytes and check for central directory locator fields.
You have described a java.io.PushbackInputStream - in addition to read(), it has an unread(byte[]) which allows you push them bck to the front of the stream, and to re-read() them again.
It's in java.io since JDK1.0 (though I admit I haven't seen a use for it until today).
It sounds a bit like a hack, but you could implement a proxy java.io.InputStream to sit between ZipInputStream and the stream you originally passed to ZipInputStream's constructor. Your proxy would stream to a buffer until you know whether it's a ZIP file or not. If not, then the buffer saves your day.