Link to home
Start Free TrialLog in
Avatar of lordparma
lordparma

asked on

Force download not working for MS Office files

I have created a JSP page to force the download of different types of files.  PDF, TXT and ZIP files download perfectly, however DOC, XLS PPT and TIFF files do not - they download but then are not correctly interpreted by the application.  A Word doc, for example, looks like:

ÐÏ à¡± á                >   þÿ                      !           #       þÿÿÿ        ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿì¥Á          ð ¿               0

For the XLS, DOC and PPT files, I get the same result if I set the MIME Type to APPLICATION/OCTET-STREAM, APPLICATION/STREAM, and APPLICATION/UNKNOWN.  I've confirmed that there is nothing wrong with the files themselves.  Interestingly, if I zip the file it downloads AND opens correctly!

Here's my code (The code comes largely from a number of answers on this site - thanks especially to cheekyci):

<%@ page import="java.util.*,java.io.*"%>
<%
  String filePath = this.getServletContext().getRealPath("/") + "/doc/";
  String fileName = request.getParameter("file");

  //determine MIME type based on fileName extension
  String extension = fileName.substring(fileName.indexOf(".")+1);
  String mimeType;
  if (extension.equals("xls")) {
    mimeType="APPLICATION/VND.MS-EXCEL";
  }
  else if (extension.equals("doc")) {
    mimeType="APPLICATION/MSWORD";
  }
  else if (extension.equals("ppt")) {
    mimeType="APPLICATION/VND.MS-POWERPOINT";
  }
  else if (extension.equals("tiff")) {
    mimeType="IMAGE/TIFF";
  }
  else {
    mimeType="APPLICATION/STREAM";    
  }
  File downloadFile = new File(filePath+fileName);
  try {
      if (downloadFile.exists()) {
        //set response headers to force download
        response.setContentType(mimeType);
        response.setHeader("Content-Disposition","attachment; filename=\""+ fileName + "\"");
         
        //stream out file
        FileInputStream fInputStream =new FileInputStream(filePath+fileName);
        ServletOutputStream fOutputStream = response.getOutputStream();
        int i;
        while ((i=fInputStream.read()) != -1) {
            fOutputStream.write(i);
        }
        fInputStream.close();
        fOutputStream.close();
      }
      else {
            System.out.println("File not found @"+filePath+fileName);
      }
  } catch (Exception exp){
     System.out.println("Exception: "+exp.getMessage());
  }
%>
Avatar of kennethxu
kennethxu

1. I'm not sure upper case of mimetype works, but I never used it and never seen it. so you might want to try lower case: e.g. application/vnd.ms-excel

2. just to be sure the fileName with out any path in it, use
response.setHeader("Content-Disposition","attachment; filename=\""+ downloadFile.getName() + "\"");

3. try it on another PC, it might be the IE/Office installation problem in a particular PC
interesting situation.

when you transfer the file onto your server are you using FTP?  Make sure the FTP mode is set to binary not ascii.

CJ
Avatar of lordparma

ASKER

I'm working on my development PC, so all files are local. That's what's so weird - I'm 'downloading' from my PC to my PC - it's the input stream and/or output stream that is corrupting or converting the Office files.

I'm running BEA Weblogic on a W2K PC, Java SKD 1.4.
kennethxu, I just tried your suggestions and unfortunately none of them made a difference.  Lowercase mimetype - no change, using downloadFile.getName() gives the same name as before, and the downloaded files appear corrupted on other PCs as well.  Thanks for the suggestions though!
just to make sure, change Content-Disposition to Content-disposition.  Also, I don't think you're supposed to have "" around the filename for the Content-disposition header.  

so instead of:

response.setHeader("Content-Disposition","attachment; filename=\""+ downloadFile.getName() + "\"");

Use

response.setHeader("Content-Disposition","attachment; filename=" + downloadFile.getName());

I changed Content-Disposition to Content-disposition, and got rid of the quotes around the filename; still the same result.  
I'm thinking now that this has more to do with the way java's FileInputStream and/or ServletOutputStream handle the binary data that makes up a Word, Excel or Powerpoint file.  I've read that the MS uses a proprietary binary format for their documents - perhaps this is the cause of the problem.
I don't think so ...  I have a servlet that does more or less exactly what you're doing.  I happen to wrap the InputStream and OutputStream with buffered streams for performance.  But I also tried your method (actually pasted your code into my servlet) and it works just fine.  Have you tried changing the content-disposition to "inline" just for testing purposes?

I'm using a servlet and you're using a JSP.  Can't think of a reason why, but could the JSP-generated servlet by hosing up the transfer somehow by putting something in the Outputstream before or after your stuff?  Check the generated source of your JSP ... or maybe just try this from a Servlet.

ASKER CERTIFIED SOLUTION
Avatar of kennethxu
kennethxu

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
this servlet can be mapped as
1. /download/*, the download file as /download/xxx.doc
2. /download, then download file as /download?filename=xxx.doc
or both.
For those of you who have responded recently - thank you - I am travelling on business and will be back in the office in a couple of days - I'll be able to test the different solutions proposed, and I'll let you know what works!  Thanks again.
kennethxu - after a really long delay, I have finally returned to accept this answer.  Thanks to all of you for your input - for some reason this code works in a java servlet and not in a jsp page.  Must be the way the jsp-->servlet conversion takes place.  In the end, we used a servlet/bean combination to retrieve the document from a database rather than a file server.