sei sicuro di settare alcuni parametri correttamentre tipo il content-type o il content-disposition?
Io ho un'applicazione java che crea un file excel e poi lo spedisce al client, da cui è possibile fare il salvataggio in locale o l'apertura.
Il codice è:

codice:
public void sendOutput(HttpServletRequest request, HttpServletResponse response) 
throws ServletException, IOException{
    request.setAttribute("Content-disposition", "attachment; filename=" +"Report_CUR.xls" );
    request.setAttribute("Content-type", "application/xls");
    request.setAttribute("pathname", "");
    request.setAttribute("filename", fileTemp.getAbsolutePath());
    request.getRequestDispatcher("/servlet/Download").forward(request, response);
  }
alla fine faccio il forward verso una servlet, il cui metodo service esegue questo codice (il codice è parametrizzato, perchè questa servlet di dowload nella mia applicazione fa il download di diversi tipi di file, non solo excel: per questo motivo non è stato messo tutto dentro una unica classe: se tu non hai problemi di generalizzazioni puoi fare tutto in un unica classe.

codice:
 public void service(HttpServletRequest request,
                      HttpServletResponse response) throws ServletException
    {
      try {
        String contentDisposition = (String)request.getAttribute("Content-disposition");
        String contentType = (String)request.getAttribute("Content-type");
        if(contentType == null) contentType = request.getParameter("conttype");
        if(contentDisposition == null) contentDisposition = request.getParameter("contdisp");

        // Regola per reperire il file - priorita' di ricerca file
        // 1° - parametri fileName e pathName da forwarding di altre servlet
        // 2° - parametri ricevuti via http da link diretti
        // 3° - informazione contenuta nell'indirizzo con cui e' chiamata
        //      la servlet (es. /c:/ftp/file.pdf) vedi <servletmapping> in
        //      web.xml


        String pathName = null;
        String fileName = (String)request.getAttribute("filename");  // da forwarding ?
        if(fileName == null)
            fileName = request.getParameter("filename");             // parametro di link o form ?
        if(fileName == null) {
            fileName = request.getServletPath();                     // address mapping ?
            pathName = "";                                           // in questo caso ho anche il path
        }
        else {
            /* in caso di forwarding o parametri devo reperire il path */
            pathName = (String)request.getAttribute("pathname");
            if(pathName == null)
                  pathName = request.getParameter("pathname");
            if(pathName == null)
                  pathName = "";
            if(pathName.length() > 0)
                pathName += (pathName.endsWith("\\") || pathName.endsWith("/") ? "" : "\\");
        }
        String canName = pathName + fileName;
        System.out.println("canName-"+canName);


        File fTemp = new File(canName);

        if (fTemp.exists() && fTemp.length()>0){
          //response.setContentLength((int)fTemp.length());
          if(contentType != null)
              response.setContentType(contentType);
          else
              response.setContentType("application/pdf");

          if(contentDisposition != null)
              response.setHeader("Content-disposition", contentDisposition);
          else
              response.setHeader("Content-disposition","attachment; filename=" +"WPDReport.pdf" );

          ServletOutputStream out = response.getOutputStream();
          FileInputStream fis = new FileInputStream(fTemp);

          int letti = 0;
          byte[]buf = new byte[10000];
          do {
             letti = fis.read(buf, 0, buf.length);
             if(letti > 0)
                  out.write(buf, 0, letti);
          } while(letti == buf.length);

          fis.close();
          out.flush();

          if(request.getAttribute("delete") != null ||
             request.getParameter("delete") != null)
              fTemp.delete();
        }

      }
      catch(Exception e) {
            ourLog.debug("Download:service-", e);
      }
    }
la parte di codice importante è essenzialmente
codice:
ServletOutputStream out = response.getOutputStream();
          FileInputStream fis = new FileInputStream(fTemp);

          int letti = 0;
          byte[]buf = new byte[10000];
          do {
             letti = fis.read(buf, 0, buf.length);
             if(letti > 0)
                  out.write(buf, 0, letti);
          } while(letti == buf.length);

          fis.close();
          out.flush();
spero di esserti stato d'aiuto e di non averti ulteriormente incasinato le idee.

ciao