I’m trying to get Tomcat to write out the servlet contents as a bzip2 file (Silly requirement perhaps but it’s apparently necessary for some integration work). I’m using the Spring framework so this is in an AbstractController.
I’m using the bzip2 library from http://www.kohsuke.org/bzip2/
I can get the contents bzipped fine but when the file is written out it seems to contain a bunch of meta data and is unrecognisable as a bzip2 file.
Here’s what I’m doing
// get the contents of my file as a byte array
byte[] fileData = file.getStoredFile();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
//create a bzip2 output stream to the byte output and write the file data to it
CBZip2OutputStream bzip = null;
try {
bzip = new CBZip2OutputStream(baos);
bzip.write(fileData, 0, fileData.length);
bzip.close();
} catch (IOException ex) {
ex.printStackTrace();
}
byte[] bzippedOutput = baos.toByteArray();
System.out.println("bzipcompress_output:\t" + bzippedOutput.length);
//now write the byte output to the servlet output
//setting content disposition means the file is downloaded rather than displayed
int outputLength = bzippedOutput.length;
String fileName = file.getFileIdentifier();
response.setBufferSize(outputLength);
response.setContentLength(outputLength);
response.setContentType("application/x-bzip2");
response.setHeader("Content-Disposition",
"attachment; filename="+fileName+";)");
This is being called from the following method in the Spring abstractcontroller
protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception
I’ve taken a few stabs at it in different approaches, including writing directly to the ServletOutput but I’m pretty stumped and can’t find any/many examples online.
Any advice from anyone who’s come across this before would be much appreciated. Alternative libraries/approaches are fine, but unfortunately it must be bzip2’d.
The posted approach is indeed weird. I’ve rewritten so that it makes more sense. Give it a try.
You see, just wrap the output stream of the response with
CBZip2OutputStreamand write thebyte[]to it.You may happen to see
IllegalStateException: Response already committedcoming after this in the server logs (with the download being correctly sent by the way), then it means that Spring is trying to forward the request/response afterwards. I don’t do Spring, so I can’t go in detail, but you should at least instruct Spring to stay away from the response. Do not let it do a mapping, forward or whatever. I think returningnullsuffices.