小菜毛毛技術(shù)分享

          與大家共同成長(zhǎng)

            BlogJava :: 首頁(yè) :: 聯(lián)系 :: 聚合  :: 管理
            164 Posts :: 141 Stories :: 94 Comments :: 0 Trackbacks
          jsp中實(shí)現(xiàn)文件下載

          (一)
          最簡(jiǎn)單的方式是在網(wǎng)頁(yè)上做超級(jí)鏈接,如:<a href="music/abc.mp3">點(diǎn)擊下載</a>。
          但是這樣服務(wù)器上的目錄資源會(huì)直接暴露給最終用戶(hù),會(huì)給網(wǎng)站帶來(lái)一些不 安全的因素。

          因此可以采用其它方式實(shí)現(xiàn)下載,可以采用:

          1、RequestDispatcher的方式進(jìn)行;

          2、采用文件流輸出的方式下載。 (推薦)



          1、采用RequestDispatcher的方式進(jìn)行

          Jsp代碼 復(fù)制代碼
          1. <%   
          2.   response.setContentType("application/x-download");//設(shè)置為下載application/x-download   
          3.   String filedownload = "/要下載的文件名";//即將下載的文件的相對(duì)路徑   
          4.   String filedisplay = "最終要顯示給用戶(hù)的保存文件名";//下載文件時(shí)顯示的文件保存名稱(chēng)   
          5.   String filenamedisplay = URLEncoder.encode(filedisplay,"UTF-8");   
          6.   response.addHeader("Content-Disposition","attachment;filename=" + filedisplay);   
          7.       
          8.   try   
          9.   {   
          10.   RequestDispatcher dis = application.getRequestDispatcher(filedownload);   
          11.   if(dis!= null)   
          12.   {   
          13.   dis.forward(request,response);   
          14.   }   
          15.   response.flushBuffer();   
          16.   }   
          17.   catch(Exception e)   
          18.   {   
          19.   e.printStackTrace();   
          20.   }   
          21.   finally   
          22.   {   
          23.       
          24.   }   
          25. %>  


          2、采用文件流輸出的方式下載

          Jsp代碼 復(fù)制代碼
          1. <%@page language="java" contentType="application/x-msdownload" pageEncoding="gb2312"%>   
          2. <%   
          3.   //關(guān)于文件下載時(shí)采用文件流輸出的方式處理:   
          4.   //加上response.reset(),并且所有的%>后面不要換行,包括最后一個(gè);   
          5.   
          6.   response.reset();//可以加也可以不加   
          7.   response.setContentType("application/x-download");   
          8.   
          9. //application.getRealPath("/main/mvplayer/CapSetup.msi");獲取的物理路徑   
          10.   
          11. String filedownload = "想辦法找到要提供下載的文件的物理路徑+文件名";   
          12.  String filedisplay = "給用戶(hù)提供的下載文件名";   
          13.   String filedisplay = URLEncoder.encode(filedisplay,"UTF-8");   
          14.   response.addHeader("Content-Disposition","attachment;filename=" + filedisplay);   
          15.   
          16.   java.io.OutputStream outp = null;   
          17.   java.io.FileInputStream in = null;   
          18.   try   
          19.   {   
          20.   outp = response.getOutputStream();   
          21.   in = new FileInputStream(filenamedownload);   
          22.   
          23.   byte[] b = new byte[1024];   
          24.   int i = 0;   
          25.   
          26.   while((i = in.read(b)) > 0)   
          27.   {   
          28.   outp.write(b, 0, i);   
          29.   }   
          30. //     
          31. outp.flush();   
          32. //要加以下兩句話(huà),否則會(huì)報(bào)錯(cuò)   
          33. //java.lang.IllegalStateException: getOutputStream() has already been called for //this response     
          34. out.clear();   
          35. out = pageContext.pushBody();   
          36. }   
          37.   catch(Exception e)   
          38.   {   
          39.   System.out.println("Error!");   
          40.   e.printStackTrace();   
          41.   }   
          42.   finally   
          43.   {   
          44.   if(in != null)   
          45.   {   
          46.   in.close();   
          47.   in = null;   
          48.   }   
          49. //這里不能關(guān)閉     
          50. //if(outp != null)   
          51.   //{   
          52.   //outp.close();   
          53.   //outp = null;   
          54.   //}   
          55.   }   
          56. %>  

          對(duì)于第二種方法,我認(rèn)為應(yīng)該是比較常用的。不過(guò)有幾個(gè)地方是值得我們注意的:

          一、采用第二種方法的主要優(yōu)點(diǎn)是實(shí)際文件的存放路徑對(duì)客戶(hù)端來(lái)說(shuō)是透明的。
          這個(gè)文件可以存在于任何你的服務(wù)器能夠取得到的地方,而客戶(hù)端不一定能直接得到。例如文件來(lái)自于數(shù)據(jù)庫(kù)或者內(nèi)部網(wǎng)絡(luò)的一個(gè)FTP服務(wù)器。還句話(huà)說(shuō),這種方式可以實(shí)現(xiàn)隱藏實(shí)際文件的URL地址。

          二、為了防止客戶(hù)端瀏覽器直接打開(kāi)目標(biāo)文件(例如在裝了MS Office套件的Windows中的IE瀏覽器可能就會(huì)直接在IE瀏覽器中打開(kāi)你想下載的doc或者xls文件),你必須在響應(yīng)頭里加入強(qiáng)制下載的MIME類(lèi)型:
          response.setContentType("application/force-download");//設(shè)置為下載application/force-download
          這樣,就可以保證在用戶(hù)點(diǎn)擊下載鏈接的時(shí)候?yàn)g覽器一定會(huì)彈出提示窗口來(lái)詢(xún)問(wèn)你是下載還是直接打開(kāi)并允許你選擇要打開(kāi)的應(yīng)用程序,除非你設(shè)置了瀏覽器的一些默認(rèn)行為。
          或者,你想讓客戶(hù)端自行處理各種不同的文件類(lèi)型,你可以在服務(wù)器的配置文件中配置MIME類(lèi)型映射,通過(guò)簡(jiǎn)單的判斷文件后綴名來(lái)處理。例如,在Tomcat中設(shè)置MIME響應(yīng)類(lèi)型:
          如果文件在客戶(hù)端中的響應(yīng)程序類(lèi)型和期望不一致,修改$TOMCAT_HOME\conf\web.xml文件中的如下部分 :
          <mime-mapping>
            <extension>zip</extension>
            <mime-type>application/zip</mime-type>
          </mime-mapping>
          <mime-mapping>
            <extension>mht</extension>
            <mime-type>message/rfc822</mime-type>
          </mime-mapping>
          ……

          三、在響應(yīng)頭中盡量不要設(shè)置瀏覽器緩存期限。
          有時(shí)候用戶(hù)在點(diǎn)擊了下載鏈接后,在彈出窗口中,用戶(hù)想直接點(diǎn)擊“打開(kāi)”,而不想保存到指定路徑。這時(shí)候如果我們?cè)陧憫?yīng)頭中限制了不允許使用瀏覽器緩存(即總是刷新),在IE瀏覽器中我們將無(wú)法直接打開(kāi)該文件。因?yàn)橄拗屏瞬辉试S使用緩存,瀏覽器無(wú)法將文件保存到臨時(shí)文件夾(即緩存)。
          也就是說(shuō),在響應(yīng)頭中不要進(jìn)行如下的設(shè)置(已注釋?zhuān)?
            //response.addHeader("pragma","NO-cache");
            //response.addHeader("Cache-Control","no-cache");
            //response.addDateHeader("Expries",0);

          四、文件名為中文或其他unicode字符時(shí)的處理。
          有時(shí)候提供下載的文件名中包含中文字符或者其他unicode字符,會(huì)導(dǎo)致瀏覽器無(wú)法正確的采用默認(rèn)的文件名保存文件。我們應(yīng)該記住在響應(yīng)頭中包含filename字段并采用ISO8859-1編碼(推薦)或者采用UTF-8編碼:
          response.setHeader("Content-disposition","attachment; filename="+new String(filename.getBytes("UTF-8"),"iso8859-1")); //采用ISO8859-1編碼
          response.setHeader("Content-disposition","attachment; filename="+URLEncoder.encode(filename, "UTF-8")); //采用UTF-8編碼
          但是,這種方式在不同的瀏覽器中表現(xiàn)也有所不同。例如在IE和Firefox中,采用ISO8859-1編碼可以正確顯示文件名,而在Opera中不管采用那種編碼,默認(rèn)保存的文件名都無(wú)法做到正確顯示。
          所以最好的方法其實(shí)就是盡量在文件名中使用ascii編碼。

          五、由于采用流的方式進(jìn)行輸入輸出,我們必須保證在使用完畢后關(guān)閉流的資源。
          一般我們把關(guān)閉流的操作放在finally塊中,以保證在程序段結(jié)束前一定會(huì)關(guān)閉流的資源:

          InputStream is = null;
          ServletOutputStream sos = null;
          try {
            is = ...; //通過(guò)某種方式讀進(jìn)數(shù)據(jù)到輸入流
            sos = response.getOutputStream(); //打開(kāi)輸入流
            byte[] buff = new byte[2048];
            int bytesRead;
            while(-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
            sos.write(buff,0,bytesRead);
            sos.flush();
            }
          } catch(IOException ex) {
            //TODO something with IOException
          } catch(Exception ex) {
            //TODO something with Exception
          } finally {
            if(is != null) {
            is.close(); //關(guān)閉輸入流
            }
            if(sos != null) {
            sos.close(); //關(guān)閉輸入流
            }
          }
          posted on 2010-01-18 13:30 小菜毛毛 閱讀(329) 評(píng)論(0)  編輯  收藏 所屬分類(lèi): J2EE相關(guān)技術(shù)與框架
          主站蜘蛛池模板: 丰宁| 福建省| 扬中市| 永康市| 韶山市| 孝昌县| 龙川县| 西乌珠穆沁旗| 大连市| 玉山县| 安康市| 和林格尔县| 巴青县| 滦南县| 高碑店市| 海兴县| 河间市| 曲阳县| 霸州市| 宣汉县| 民权县| 石家庄市| 温宿县| 东莞市| 阳新县| 乌拉特后旗| 类乌齐县| 孙吴县| 高雄县| 工布江达县| 大竹县| 忻州市| 莱西市| 凤凰县| 阜平县| 扶余县| 鸡西市| 安乡县| 百色市| 洛川县| 邻水|