JSP實現文件下載

比如,downLoadFile.jsp?fileName=d:/file/20150227-0002.ZIP,實現下載。

<%@page contentType = " text/html; charset=GBK"  pageEncoding ="GBK"   %> 
<%@ page  import = " java.io.*, java.util.*, java.text.* "   %> 

<%! 
     /** 
     *  If returns true, then should return a 304 (HTTP_NOT_MODIFIED)
      */ 
     public   static   boolean  checkFor304( HttpServletRequest req,
                                       File file )
    {
         // 
         //   We'll do some handling for CONDITIONAL GET (and return a 304)
         //   If the client has set the following headers, do not try for a 304.
         // 
         //     pragma: no-cache
         //     cache-control: no-cache
         //

         if (  "no-cache" .equalsIgnoreCase(req.getHeader( "Pragma" ))
             ||   "no-cache" .equalsIgnoreCase(req.getHeader( "cache-control" )))
        {
             //  Wants specifically a fresh copy 
        }
         else 
        {
             // 
             //   HTTP 1.1 ETags go first
             //
            String thisTag  =  Long.toString(file.lastModified());

            String eTag  =  req.getHeader(  "If-None-Match"  );

             if ( eTag  !=   null  )
            {
                 if ( eTag.equals(thisTag) )
                {
                     return   true ;
                }
            }

             // 
             //   Next, try if-modified-since
             //
            DateFormat rfcDateFormat  =   new  SimpleDateFormat( "EEE, dd MMM yyyy HH:mm:ss z" );
            Date lastModified  =   new  Date(file.lastModified());

             try 
            {
                 long  ifModifiedSince  =  req.getDateHeader( "If-Modified-Since" );

                 // log.info("ifModifiedSince:"+ifModifiedSince); 
                 if ( ifModifiedSince  !=   - 1  )
                {
                     long  lastModifiedTime  =  lastModified.getTime();

                     // log.info("lastModifiedTime:" + lastModifiedTime); 
                     if ( lastModifiedTime  <=  ifModifiedSince )
                    {
                         return   true ;
                    }
                }
                 else 
                {
                     try 
                    {
                        String s  =  req.getHeader( "If-Modified-Since" );

                         if ( s  !=   null  )
                        {
                            Date ifModifiedSinceDate  =  rfcDateFormat.parse(s);
                             // log.info("ifModifiedSinceDate:" + ifModifiedSinceDate); 
                             if ( lastModified.before(ifModifiedSinceDate) )
                            {
                                 return   true ;
                            }
                        }
                    }
                     catch  (ParseException e)
                    {
                         // log.warn(e.getLocalizedMessage(), e); 
                    }
                }
            }
             catch ( IllegalArgumentException e )
            {
                 //  Illegal date/time header format.
                 //  We fail quietly, and return false.
                 //  FIXME: Should really move to ETags. 
            }
        }

         return   false ;
    }
%> 

<% 
     //  String filePath = "c:/文檔.doc";
     //  如果是 WEB APP 下的相對路徑文件, 請使用下列代碼: 
    String filePath  = request.getParameter("fileName");
     boolean  isInline  =   false ; //  是否允許直接在瀏覽器內打開(如果瀏覽器能夠預覽此文件內容,
     //  那麼文件將被打開, 否則會提示下載)

     //  清空緩衝區, 防止頁面中的空行, 空格添加到要下載的文件內容中去
     //  如果不清空的話在調用 response.reset() 的時候 Tomcat 會報錯
     //  java.lang.IllegalStateException: getOutputStream() has already been called for
     //  this response, 
    out.clear();

     //  {{{ BEA Weblogic 必讀
     //  修正 Bea Weblogic 出現 "getOutputStream() has already been called for this response"錯誤的問題
     //  關於文件下載時採用文件流輸出的方式處理:
     //  加上response.reset(),並且所有的%>後面不要換行,包括最後一個;
     //  因爲Application Server在處理編譯jsp時對於%>和<%之間的內容一般是原樣輸出,而且默認是PrintWriter,
     //  而你卻要進行流輸出:ServletOutputStream,這樣做相當於試圖在Servlet中使用兩種輸出機制,
     //  就會發生:getOutputStream() has already been called for this response的錯誤
     //  詳細請見《More Java Pitfill》一書的第二部分 Web層Item 33:試圖在Servlet中使用兩種輸出機制 270
     //  而且如果有換行,對於文本文件沒有什麼問題,但是對於其它格式,比如AutoCAD、Word、Excel等文件
     // 下載下來的文件中就會多出一些換行符0x0d和0x0a,這樣可能導致某些格式的文件無法打開,有些也可以正常打開。
     //  同時這種方式也能清空緩衝區, 防止頁面中的空行等輸出到下載內容裏去 
    response.reset();
     //  }}} 

     try  {
        java.io.File f  =   new  java.io.File(filePath);
         if  (f.exists()  &&  f.canRead()) {
             //  我們要檢查客戶端的緩存中是否已經有了此文件的最新版本, 這時候就告訴
             //  客戶端無需重新下載了, 當然如果不想檢查也沒有關係 
             if ( checkFor304( request, f ) )
            {
                 //  客戶端已經有了最新版本, 返回 304 
                response.sendError( HttpServletResponse.SC_NOT_MODIFIED );
                 return ;
            }

             //  從服務器的配置來讀取文件的 contentType 並設置此contentType, 不推薦設置爲
             //  application/x-download, 因爲有時候我們的客戶可能會希望在瀏覽器裏直接打開,
             //  如 Excel 報表, 而且 application/x-download 也不是一個標準的 mime type,
             //  似乎 FireFox 就不認識這種格式的 mime type 
            String mimetype  =   null ;
            mimetype  =  application.getMimeType( filePath );
             if ( mimetype  ==   null  )
            {
                mimetype  =   "application/octet-stream;charset=ISO8859-1" ;
            }


             //  IE 的話就只能用 IE 才認識的頭才能下載 HTML 文件, 否則 IE 必定要打開此文件! 
            String ua  =  request.getHeader( "User-Agent" ); //  獲取終端類型 
             if (ua  ==   null ) ua  =   "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0;)" ;
             boolean  isIE  =  ua.toLowerCase().indexOf( "msie" )  !=   - 1 ; //  是否爲 IE 

             if (isIE  &&   ! isInline) {
                mimetype  =   "application/x-msdownload" ;
            }

             System.out.println("mimetype="+mimetype);
             response.setContentType( mimetype );
             //  下面我們將設法讓客戶端保存文件的時候顯示正確的文件名, 具體就是將文件名
             //  轉換爲 ISO8859-1 編碼 
            String downFileName  =   new  String(f.getName().getBytes(),  "ISO8859-1" );

            String inlineType  =  isInline  ?   "inline"  :  "attachment" ; //  是否內聯附件
            System.out.println("inlineType1 ="+inlineType);
             //  or using this, but this header might not supported by FireFox
             // response.setContentType("application/x-download"); 
            response.setHeader ( "Content-Disposition" , inlineType  +   ";filename=\""+  downFileName  +   " \"" ); 

            response.setContentLength(( int ) f.length()); //  設置下載內容大小 

             byte [] buffer  =   new   byte [ 4096 ]; //  緩衝區 
            BufferedOutputStream output  =   null ;
            BufferedInputStream input  =   null ;

             //
             try  {
                output  =   new  BufferedOutputStream(response.getOutputStream());
                input  =   new  BufferedInputStream( new  FileInputStream(f));

                 int  n  =  ( - 1 );
                 while  ((n  =  input.read(buffer,  0 ,  4096 ))  >   - 1 ) {
                    output.write(buffer,  0 , n);
                }
                response.flushBuffer();
            }
             catch  (Exception e) {
            }  //  用戶可能取消了下載 
             finally  {
                 if  (input  !=   null ) input.close();
                 if  (output  !=   null ) output.close();
            }
        }    
         return ;
    }  catch  (Exception ex) {
        ex.printStackTrace(); 
    }
     //  如果下載失敗了就告訴用戶此文件不存在 
    response.sendError( 404 );
%> 



比如,downLoadFile.jsp?fileName=d:/file/20150227-0002.ZIP,實現下載。


發佈了61 篇原創文章 · 獲贊 2 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章