Oops Null Pointer

Java programming related

Sending PDF files in the response

To send PDF files so that most browsers will display them I’ve found the following headers work:

  • Content-Disposition: inline; filename=sample.pdf or Content-Disposition: attachment; filename=sample.pdf
  • Expires: 0
  • Cache-Control: must-revalidate, post-check=0, pre-check=0
  • Pragma: public
  • Content-Type: application/pdf
  • Content-Length: <number of bytes>

Here is some rough Java to stream an input stream to the HttpServletResponse.

public static void streamInputToResponse(HttpServletResponse resp, boolean isInline, String contentType, String filename,
		InputStream in, int length) throws IOException {
	ServletOutputStream outstr = null;
	
	try {
		if (length > Integer.MAX_VALUE) {
			throw new IOException("File to large to stream");
		}
		
		outstr = resp.getOutputStream();
		
		// Setting required headers
		resp.setContentLength(length);
		resp.setContentType(contentType);
		String inlineOrAttachment = isInline ? "inline;" : "attachment;";
		resp.setHeader("Content-Disposition", inlineOrAttachment + " filename=" + filename);
		
		// setting some extra response headers to sooth browser issues
		resp.setHeader("Expires", "0");
		resp.setHeader("Cache-Control", "must-revalidate, post-check=0, pre-check=0");
		resp.setHeader("Pragma", "public");

		IOUtils.copy(in, outstr);
		outstr.flush();
	}
	catch (IOException e) {
		String errorStr = "Error Streaming data to servlet output stream" + ": " + e.getMessage();

		try {
			if (outstr != null) {
				outstr.print(errorStr);
				outstr.flush();
			}
		}
		catch (IOException e1) {
			logger.warn("Error flushing servlet output stream: " + e1.getMessage());
		}
		
		throw e;
	}
	finally {
		IOUtils.closeQuietly(in);
		IOUtils.closeQuietly(outstr);
	}
}

Update:
The Restlet framework has some issues with PDFs when used in JBoss / Tomcat. Tomcat is appending a charset=UTF8 that appears to stop chrome’s built in PDF reader from loading (Chrome 11). Not setting the content length appeared to help while surprisingly not breaking IE.
Also with JBoss and authentication a no-cache header is added and the Restlet framework doesn’t remove it (even if you add your own Cache-Control header). See here for a way to disable this behaviour.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: