?
Solved

Force download not working for MS Office files

Posted on 2003-03-27
12
Medium Priority
?
10,216 Views
Last Modified: 2007-12-19
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());
  }
%>
0
Comment
Question by:lordparma
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 3
  • 2
  • +1
12 Comments
 
LVL 14

Expert Comment

by:kennethxu
ID: 8218944
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
0
 
LVL 19

Expert Comment

by:cheekycj
ID: 8219008
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
0
 

Author Comment

by:lordparma
ID: 8223703
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.
0
Industry Leaders: 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!

 

Author Comment

by:lordparma
ID: 8223716
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!
0
 
LVL 7

Expert Comment

by:damonf
ID: 8224782
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());

0
 

Author Comment

by:lordparma
ID: 8225134
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.
0
 
LVL 7

Expert Comment

by:damonf
ID: 8225372
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.

0
 
LVL 19

Expert Comment

by:cheekycj
ID: 8225385
0
 
LVL 14

Accepted Solution

by:
kennethxu earned 225 total points
ID: 8225697
anyway, I always use servlet to download files, jsp is good for generate text information, but always have problem for binary data, I know somebody success, but I also heard a lot of problems. try this:
import java.io.*;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public final class DownloadServlet extends HttpServlet {
    private static final String basePath = "/doc";

    public void service(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, java.io.IOException
    {
        String filePath = request.getPathInfo();
        String filename = request.getParameter( "filename" );
     if( filePath == null && filename != null ) filePath = "/" + filename;
     if( filename == null ) filename = filePath;
     if( filename != null ) filename = (new File(filename)).getName();

        if( filePath != null ) {
          InputStream in = null;
          OutputStream out = null;
          try {
                 in = getServletContext().getResourceAsStream(basePath + filePath);
              if( in != null ) {
                        out = new BufferedOutputStream( response.getOutputStream() );
                        in = new BufferedInputStream( in );
                        String contentType = getServletConfig().getServletContext().getMimeType( filename );
                        if( contentType == null ) contentType = "application/unknow";
                        System.out.println( "contentType: " + contentType );
                        response.setHeader("Content-Disposition","attachment; filename=\"" + filename + "\"");
                        int c; while( ( c=in.read() ) != -1 ) out.write( c );
                        return;
                 }
          } finally {
               if( in != null ) try { in.close(); } catch( Exception e ) {}
               if( out != null ) try { out.close(); } catch( Exception e ) {}
          }
     }
     response.sendError( HttpServletResponse.SC_NOT_FOUND );
    }
}
0
 
LVL 14

Expert Comment

by:kennethxu
ID: 8225718
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.
0
 

Author Comment

by:lordparma
ID: 8238457
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.
0
 

Author Comment

by:lordparma
ID: 8613893
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.
0

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In the absence of a fully-fledged GPO Management product like AGPM, the script in this article will provide you with a simple way to watch the domain (or a select OU) for GPOs changes and automatically take backups when policies are added, removed o…
The top devops trends for 2017 are focused on improved deployment frequency, decreased lead time for change and decreased MTTR.
Add bar graphs to Access queries using Unicode block characters. Graphs appear on every record in the color you want. Give life to numbers. Hopes this gives you ideas on visualizing your data in new ways ~ Create a calculated field in a query: …
Have you created a query with information for a calendar? ... and then, abra-cadabra, the calendar is done?! I am going to show you how to make that happen. Visualize your data!  ... really see it To use the code to create a calendar from a q…

770 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question