• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 4161
  • Last Modified:

Display a PDF or Excel file in a JSP

I have a JSP displaying a table. The last columns of each row shows a button (better a link?) which causes generating either a PDF or a MS Excel file.

I want to display the generated file in a new browser window so that the user can choose to print or to save the file. How can I achieve this?
0
dirku
Asked:
dirku
  • 2
  • 2
1 Solution
 
enachemcCommented:
you can only do that in Internet Explorer. This is a nonstandard feature of IE. Just provide the apropiate content-type header to the document when sending it to the client, and IE will take care of it. You will need a servlet to do this.
0
 
dirkuAuthor Commented:
Well, it's ok that the browser asks the user if he wants to open the file with a particular application (eg. MS Excel) or if he wants to save the file.

I am already generating the file using a servlet. The resulting file is located somewhere in the file system. What is the Java code in the servlet to send the file back to the user/browser?

In the JSP there is the button to submit the request to the server.
The servlet is creating the PDF/Excel file and stores it in the server's file system.
--> What's next? How can I get the result back to the user? The requested file (PDF/Excel) shall not be displayed in the browser window which shows the JSP with the list/table. I want to 'stay there' and open another browser asjing the user to open/save the report.
0
 
enachemcCommented:
you have two options for serving the file back to the user:
1. place the file in a directory within your server and let the user access the file as any other file on your web server
2. if you, from any reason, do not want to do that, will have to make the servlet feed the content of the file to the user. Just open an input stream for the file and feed it to the output stream of the servlet (not the print writer); send along the required headers (content type, attachement name, size - make sure you send the headers prior to sending evena byte from the file, or you'll receive errors);
0
 
dasmaerCommented:
If you get your servlet to send the following HTTP headers to the browser (for pdf):

Content-type: application/pdf
Content-Disposition: attachment; filename="downloaded.pdf"

This will force the browser to display a save file dialog. When you want the file to be shown inline, change to:

Content-type: application/pdf
Content-Disposition: inline; filename="downloaded.pdf"

However, this will not always work... Firefox for example will have trouble opening an Excel viewer and will get a file download prompt anyway.

If you want to have the content dynamically streamed to the brower - keep the code above, but write a servlet that will write a byte stream and name it something like "/streamer" (or whatever it is that is creating your spreadsheet/pdf) and have the filename part of the header point to your new servlet.  

For this solution you'd need two JSP's:
   1: the presentation page that will first attempt to send the headers outlined above. If the
       users browser can't handle it, then give them some handy link in the page so they can
       still download it.
   2: the servlet that generates your excel spreadsheet.

What you do is submit to your spreadsheet servlet, and your spreadsheet servlet can then make the spreadsheet, then forward to the presentation page...

hope this solves your problem. post me back if not.
0
 
dirkuAuthor Commented:
I played around after reading some documentation and now I implemented it this way:
          String fileFormat = request.getParameter("fileFormat");
            
            if ( fileFormat != null )
            {
                  Integer dataId = null;
                  try {
                        dataId = new Integer(RequestUtils.getRequiredIntParameter( request,
                              "dataId" ));
                  } catch (ServletRequestBindingException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                  }
            
                  // hier ggf. schon Format prüfen...
                  String fileUrl = checklistApplicationManager.downloadChecklist(dataId,
                        fileFormat,
                        request.getSession().getServletContext().getRealPath(""));

                  ServletOutputStream out = response.getOutputStream();

                  File file = new File(fileUrl);
                  
                  response.setHeader("Pragma", "public");
                  response.setHeader("Expires", "0");
                  response.setHeader("Cache-Control", "must-revalidate, post-check=0, pre-check=0");
                  //response.setHeader("Content-Type", "application/octet-stream");
                  if ( fileFormat.equalsIgnoreCase("pdf") )
                  {
                        response.setHeader("Content-Type", "application/pdf");
                  } else if ( fileFormat.equalsIgnoreCase("xls") )
                  {
                        response.setHeader("Content-Type", "application/vnd.ms-excel");
                  } else
                  {
                        response.setHeader("Content-Type", "application/octet-stream");
                  }
                  response.setHeader("Content-Transfer-Encoding", "binary");
                  response.setHeader("Content-Length", String.valueOf(file.length()));
                  // Display an open/download prompt to the user.
                  response.setHeader("Content-Disposition", "attachment; filename=\"" + file.getName() + "\"");
                  // Open the file within the browser using a browser plugin instead
                  // of the standalone application.
                  //response.setHeader("Content-Disposition", "inline; filename=\"" + file.getName() + "\"");
                  
                  BufferedInputStream is = new BufferedInputStream(new FileInputStream(file));
                  byte[] buf = new byte[4 * 1024]; // 4K buffer
                  int bytesRead;
                  while ((bytesRead = is.read(buf)) != -1)
                  {
                        out.write(buf, 0, bytesRead);
                  }//end while ((bytesRead = is.read(buf)) != -1)
                  is.close();
                  out.close();
                  
                  checklistApplicationManager.deleteFile(fileUrl);
            }

Well, dasmaer, although implemented independently looks quiet similar to what you've suggested, doesn't it?

I think it would be fair to grant the points to you. (Hehe, I should have post my solution earlier.)

Thanks a lot and best regards form Berlin, Gemrany.

dirku
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 2
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now