tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
Subject Byte Serving and PDFs with the DefaultServlet
Date Thu, 09 Oct 2008 12:45:08 GMT
Hello, I'm new to the list. Hello to every one. Sorry if I'm posting this 
message in the wrong place. If so please advise me to fix it.

I was asked to make a PDF functionality called Fast Web View work in a 
Tomcat application. In my initial tests, as I will describe, it did not 

I started downloading the version 6.0.18 and after that I downloaded the 
trunk SVN branch and compiled every thing (comment: a hard job at the 
first time, ah? sorry, I had many web proxy issues), 

I wrote a small HTML just for testing purpose. The "index.html" file is 
something like:

    <meta http-equiv="Accept-Ranges" content="bytes">
    <table border="1" align="center">
      <tr>   <td align='center' valign='middle'> 
          <a href='FIRST_FAST_WEB_VIEW_READY.PDF' 
        <td align='center' valign='middle'>32.09 MB   </td>
      <tr>  <td align='center' valign='middle'>
        <td align='center' valign='middle'>41.72 MB  </td>
      <tr> <td align='center' valign='middle'> 
          <a href='NTH_FAST_WEB_VIEW_READY.PDF' 
        <td align='center' valign='middle'>25.83 MB   </td>

I just created a folder in the webapps folder named PDFs and placed 
everything there.

When I started Tomcat, opened the page and click on the first PDF link (on 
other link the result was the same) with the address 
http://localhost:8080/PDFs/, I got the following result:
- The file was found by Tomcat
- Adobe Reader works properlly requesting a "byte served" content (I also 
configured the property useAcceptRanges on the web.xml file)
- Tomcat returned a header response 200 OK and some data
- Adobe requests a partial content with a few range descriptors like: 
500-999, 7000-7999 (I rounded the sample here)
- Tomcat send a response (http 206)  multipart/byterange for the above 
- Adobe Reader locks and don't ask any more ranges
- The browser also locks and after a long wait time it returns a error 
message of problems on file.

I started them analysing the response stream with an http protocol 
analyser plug-in for the browser.

In the RFC2616 I noted that the response should be as the below sample 
cutted from the RFC2616:

  HTTP/1.1 206 Partial Content
   Date: Wed, 15 Nov 1995 06:25:24 GMT
   Last-Modified: Wed, 15 Nov 1995 04:58:08 GMT
   Content-type: multipart/byteranges; boundary=THIS_STRING_SEPARATES

   Content-type: application/pdf
   Content-range: bytes 500-999/8000

   ...the first range...
   Content-type: application/pdf
   Content-range: bytes 7000-7999/8000

   ...the second range

But I noted that Tomcat was returning the following stream:

  HTTP/1.1 206 Partial Content
   Date: Wed, 15 Nov 1995 06:25:24 GMT
   Last-Modified: Wed, 15 Nov 1995 04:58:08 GMT
   Content-type: multipart/byteranges; boundary=THIS_STRING_SEPARATES

   Content-range: bytes 500-999/8000

   ...the first range...
   Content-range: bytes 7000-7999/8000

   ...the second range

Please note the lack of the "Content-type: application/pdf" message and 
additional line break from the RFC sample and the Tomcat stream.

After some research I found the DefaultServlet Class where the stream for 
partial content and multi range requests are served.
On Tomcat 6.0 at java\org\apache\catalina\servlets and on Tomcat 5.5 at 

The first thing that happens to make it work was the add of 
"useAcceptRanges" on the config file (web.xml) and the fix for it on 
Tomcat 6.0.x class source code on the SVN repository (thankyou). It really 
made difference because the HTTP header response must have "Accept-Ranges: 
bytes" string to allow clients make byte requests (at least Adobe Reader).

The second thing is in the "copy" methods. There is a check for the 
"contentType" variable and for any reason the method that try to retrieve 
its value, before the call for "copy" method, is always returning null.
So, in the if statement within the "copy" methods:

            if (contentType != null)
                ostream.println("Content-Type: " + contentType);


            if (contentType != null)
                writer.println("Content-type: " + contentType);

I added a "forced" result of :

            if (contentType != null)
                ostream.println("Content-type: " + contentType);
                ostream.println("Content-type: application/pdf");


            if (contentType != null)
                writer.println("Content-type: " + contentType);
                writer.println("Content-type: application/pdf");

In my environment it is sufficient because my big deal is with PDF files, 
but I know that it is not the most elegant solution neither can be a 
definitive solution.

As I am not a java programmer, I ask for the list to handle this issue.
If it sound completely nuts please forgive me.
I'm available to help with tests for this issue. Please contact me through 
the list or directly.

Best regards to all. 

Antonio Vitor Elias Swaid Jr
Technical Publications Development
EMBRAER - São José dos Campos
Fone: +55 12 3927-8364 Fax: +55 12 3927-3132
This message is intended solely for the use of its addressee and may 
contain privileged or confidential information. If you are not the 
addressee you should not distribute, copy or file this message. In this 
case, please notify the sender and destroy its contents immediately.
Esta mensagem é para uso exclusivo de seu destinatário e pode conter 
informações privilegiadas e confidenciais. Se você não é o destinatário 
não deve distribuir, copiar ou arquivar a mensagem. Neste caso, por favor, 
notifique o remetente da mesma e destrua imediatamente a mensagem.
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message