Stream Both Character and Binary Data via a Servlet

very programmer can quite easily write a servlet that can perform character streaming of XML or HTML data. As long as the proper MIME type is set before the data is streamed, the process is pretty simple (response.setContentType("text/xml"); sets XML content, while response.setContentType("text/html"); sets HTML).

The following code provides an example of streamCharacterData(), the method for character streaming:

/** This Method handles streaming Character data* 

* @param String urlstr ex: http://localhost/test.pdf etc.* @param String format ex: xml or HTML etc.* @param PrintWriter outstr* @param HttpServletResponse resp*/private void streamCharacterData(String urlstr,String format,
PrintWriter outstr, HttpServletResponse resp){String ErrorStr = null;try{ //find the right MIME type and set it as contenttype resp.setContentType(getMimeType(format)); InputStream in = null; try{ URL url = new URL(urlstr); URLConnection urlc= url.openConnection(); int length = urlc.getContentLength(); in = urlc.getInputStream(); resp.setContentLength(length); int ch; while ( (ch = in.read()) != -1 ) { outstr.print( (char)ch ); } } catch (Exception e) { e.printStackTrace(); ErrorStr = "Error Streaming the Data"; outstr.print(ErrorStr); } finally { if( in != null ) { in.close(); } if( outstr != null ) { outstr.flush(); outstr.close(); } } } catch(Exception e){ e.printStackTrace(); }}

In much the same way, you can also stream binary content, such as PDF, audio, video, image, doc, and XLS files, but the process is trickier than streaming character data. For example, if you try to stream a PDF file that contains a special image or font with the same servlet you use to stream XML or HTML content, the PDF reader will raise an error: “There was an error processing a page. Too few Operands.”

The way to avoid such errors when you’re trying to stream both character and binary data is to stream the binary content right way. This article provides a streaming solution that simplifies this procedure. Figure 1 shows an overall view of the solution’s design.

Click to enlarge
Figure 1: Streaming Both Character and Binary Data via a Servlet

This simple six-step tutorial guides you through the streaming solution.



How do I stream both binary and character data with a servlet when I can’t just use the java.io class PrintWriter?



Write a servlet that sets the appropriate MIME type and utilizes ServletOutPutStream to stream both binary and character data.Step One
Set the appropriate MIME type based on the format with which you’re working. The getMimeType() method supports various MIME types:

/* * This Method Returns the right MIME type for a particular  format * 

* @param String format ex: xml or HTML etc. * @return String MIMEtype */ private String getMimeType(String format) { if(format.equalsIgnoreCase("pdf")) //check the out type return "application/pdf"; else if(format.equalsIgnoreCase("audio_basic")) return "audio/basic"; else if(format.equalsIgnoreCase("audio_wav")) return "audio/wav"; else if(format.equalsIgnoreCase("image_gif")) return "image/gif"; else if(format.equalsIgnoreCase("image_jpeg")) return "image/jpeg"; else if(format.equalsIgnoreCase("image_bmp")) return "image/bmp"; else if(format.equalsIgnoreCase("image_x-png")) return "image/x-png"; else if(format.equalsIgnoreCase("msdownload")) return "application/x-msdownload"; else if(format.equalsIgnoreCase("video_avi")) return "video/avi"; else if(format.equalsIgnoreCase("video_mpeg")) return "video/mpeg"; else if(format.equalsIgnoreCase("html")) return "text/html"; else if(format.equalsIgnoreCase("xml")) return "text/xml"; else return null; }

Step Two
Get the reference to the right OutPutStream. Use ServletOutPutStream, where as for character data you’d use PrintWriter, the java.io class that prints objects to a text-output stream. This following snippet is for binary data:

ServletOutputStream sOutStream = response.getOutputStream();

Step Three
Create BufferedInputStream from the InputStream:

BufferedInputStream bis = null;InputStream in = urlc.getInputStream();bis = new BufferedInputStream(in);

Step Four
Create BufferedOutPutStream with a new ServletOutPutStream to which you can write:

BufferedOutputStream bos = null;              bos = new BufferedOutputStream(sOutStream);

Step Five
Read in to the bytes array from BufferedInputStream:

byte[] buff = new byte[length];int bytesRead;// Simple read/write loop.while(-1 != (bytesRead = bis.read(buff, 0, buff.length))) { 	bos.write(buff, 0, bytesRead);}

Step Six
Write on to BufferedOutPutStream from the bytes array, which in turn streams to the client. Use the streamBinaryData() method for binary data streaming:

/* * This Method Handles streaming Binary data * 

* @param String urlstr ex: http://localhost/test.pdf etc. * @param String format ex: pdf or audio_wav or msdocuments etc. * @param ServletOutputStream outstr * @param HttpServletResponse resp */ private void streamBinaryData(String urlstr,String format,
ServletOutputStream outstr, HttpServletResponse resp) { String ErrorStr = null; try{ //find the right MIME type and set it as contenttype resp.setContentType(getMimeType(format)); BufferedInputStream bis = null; BufferedOutputStream bos = null; try{ URL url = new URL(urlstr); URLConnection urlc= url.openConnection(); int length = urlc.getContentLength(); resp.setContentLength(length); // Use Buffered Stream for reading/writing. InputStream in = urlc.getInputStream(); bis = new BufferedInputStream(in); bos = new BufferedOutputStream(outstr); byte[] buff = new byte[length]; int bytesRead; // Simple read/write loop. while(-1 != (bytesRead = bis.read(buff, 0, buff.length))) { bos.write(buff, 0, bytesRead); } } catch (Exception e) { e.printStackTrace(); ErrorStr = "Error Streaming the Data"; outstr.print(ErrorStr); } finally { if( bis != null ) { bis.close(); } if( bos != null ) { bos.close(); } if( outstr != null ) { outstr.flush(); outstr.close(); } } } catch(Exception e){ e.printStackTrace(); } }

Installation Procedure
Compile the StreamingContent.java file provided in this article, and copy the class file to the “doc” directory of your Web server. Be sure to configure your web.xml file to contain information.

Copy a few sample files (.HTML, .pdf, .xml, .gif, .jpeg, .wav, .avi, .mpeg, etc.) into the “doc” directory of your Web server. If you’re using Microsoft IIS, copy them into the wwwroot directory.

URL Request Examples
Try the following URLs to test your streams. Replace “server” with the actual machine name:

  • http://server/servlet/StreamingContent?url=http://localhost/help.gif&format=image_gif
  • http://server/servlet/StreamingContent?url=http://localhost/help.pdf&format=pdf
  • http://server/servlet/StreamingContent?url=http://localhost/help.doc&format=msdownload
  • http://server/servlet/StreamingContent?url=http://localhost/help.html&format=html
  • http://server/servlet/StreamingContent?url=http://localhost/help.xml&format=xml
  • Don’t Count Only on PrintWriter
    Use this solution whenever you need a HTTP servlet to stream various types of document that are both binary and character data, such as HTML, XML, PDF, Word, spreadsheet, and PowerPoint. Don’t assume that PrintWriter will stream binary and character data; it won’t always do it.

    Share the Post:
    Share on facebook
    Share on twitter
    Share on linkedin

    More From DevX