I have a few Java servlets (3.x – Tomcat 8) running that generate and return PDF documents. I’ve never had any problems with any of them. I recently wrote a new servlet to also create and return a PDF document, and this new servlet is using the exact same piece of response code as the others are using:
response.reset(); response.setContentType("application/pdf"); response.setHeader("Content-Transfer-Encoding", "binary"); response.setHeader("Content-Disposition","attachment; filename=\""+filename+".pdf\""); response.setContentLength(pdfBytes.length); System.out.println("# Bytes => " + pdfBytes.length); ServletOutputStream sos = response.getOutputStream(); BufferedOutputStream bos = new BufferedOutputStream(sos); bos.write(pdfBytes); sos.flush(); sos.close();
As I said, this has been working fine with the others, but when I call the new servlet, it returns 0 bytes, even though the print statement above has a non-zero value.
However, if I change the response writing code above to:
OutputStream os = response.getOutputStream(); os.write(pdfBytes); os.flush(); os.close();
…it works fine, returning a well-formed PDF document. Why might this be happening?
You’re not flushing the
BufferedOutputStream – so it’s buffering all your data. You should flush that, not the
However, if you’re only writing a single byte array, there’s no point in using
BufferedOutputStream anyway – and you shouldn’t need to explicitly flush anyway, as closing will flush. So you just need:
ServletOutputStream sos = response.getOutputStream(); sos.write(pdfBytes); // Unclear whether *this* is needed, either. sos.close();
I’d personally expect the servlet container to close the output stream, but it’s not clear from the docs. Whether you want to close it if an exception occurs is a different matter…
you should really flush and close