1. 程式人生 > >IO流下載檔案

IO流下載檔案

IO流的下載,今天專案寫的,遇到的問題都會寫在下面,如有哪裡寫的不好,輕噴。
IO流簡介:
流的定義:流是指一連串流動的字元,是以先進先出方式傳送資訊的通道。
按流向分:輸出流:OutputStreamWriter為基類
輸入流:InputStreamReader為基類
按處理資料單元劃分:位元組流:位元組輸入流:InputStream基類
位元組輸出流:OutputStream基類
字元流:字元輸入流:Reader

基類
位元組輸出流:Writer基類
(位元組流是 8 位通用位元組流,字元流是16位Unicode字元流**)

public void download(HttpServletRequest request, HttpServletResponse response) {
        InputStream fis=null;
        OutputStream toClient=null;
        try {
            //獲取下載的路徑
            File file=new
File("C:\\Users\\kinggao1\\Desktop\\工作周總結.docx"); //獲取檔名 String filename=file.getName(); //取得檔案的字尾名 String ext=filename.substring(filename.lastIndexOf(".")+1).toUpperCase(); //以流的形式下載檔案 fis=new BufferedInputStream(new FileInputStream(file)); System.out
.println("檔案大小:"+fis.available()); //建立一個和檔案一樣大小的快取區 byte[] buffer=new byte[fis.available()]; //讀取流 fis.read(buffer); //清空首部空白行 response.reset(); //設定檔案下載後的指定檔名 response.addHeader("Content-Disposition", "attachment;filename=" + new String(filename.getBytes("gb2312"),"ISO8859-1")); response.addHeader("Content-Length", "" + file.length()); //response.getOutputStream() 獲得位元組流,通過該位元組流的write(byte[] bytes)可以向response緩衝區中寫入位元組,再由Tomcat伺服器將位元組內容組成Http響應返回給瀏覽器。 toClient = new BufferedOutputStream(response.getOutputStream()); response.setContentType("application/octet-stream"); //將buffer 個位元組從指定的 byte 陣列寫入此輸出流。 toClient.write(buffer); //重新整理此緩衝的輸出流。這迫使所有緩衝的輸出位元組被寫出到底層輸出流中。 把快取區的資料全部寫出 toClient.flush(); } catch (IOException e) { e.printStackTrace(); } finally { try { //關閉流 fis.close(); //關閉緩衝輸出流 toClient.close(); } catch (IOException e) { e.printStackTrace(); } } }
  • response.addHeader
    檔案下載,指定預設名
Response.AddHeader("content-type","application/x-msdownload"); // 限制類型
Response.AddHeader("Content-Disposition","attachment;filename=檔名.rar");// 下載後的檔名,這裡如果檔名是中文,在下載時會出現亂碼

Tips
response.setHeader()下載中文檔名亂碼問題
response.setHeader(“ContentDisposition”,”attachment;filename=”+java.net.URLEncoder.encode(fileName, “UTF-8”));

下載的程式裡有了上面一句,一般在IE6的下載提示框上將正確顯示檔案的名字,無論是簡體中文,還是日文。不過當時確實沒有仔細測試檔名為很長的中文檔名的情況。現如今經過仔細測試,發現文字只要超過17個字,就不能下載了。分析如下:

一. 通過原來的方式,也就是先用URLEncoder編碼,當中文文字超過17個時,IE6 無法下載檔案。這是IE的bug,參見微軟的知識庫文章 KB816868 。原因可能是IE在處理 Response Header 的時候,對header的長度限制在150位元組左右。而一個漢字編碼成UTF-8是9個位元組,那麼17個字便是153個位元組,所以會報錯。而且不跟字尾也不對.

二. 解決方案:將檔名編碼成ISO8859-1是有效的解決方案,程式碼如下:

response.setHeader(“ContentDisposition”,”attachment;filename=”+newString(fileName.getBytes(“gb2312”), “ISO8859-1” ) );

在確保附件檔名都是簡體中文字的情況下,那麼這個辦法確實是最有效的,不用讓客戶逐個的升級IE。如果臺灣同胞用,把gb2312改成big5就行。但現在的系統通常都加入了 國際化的支援,普遍使用UTF-8。如果檔名中又有簡體中文字,又有繁體中文,還有日文。那麼亂碼便產生了。另外,在上Firefox (v1.0-en)下載也是亂碼。

  • BufferedInputStream

帶緩衝區的輸入流,預設緩衝區大小是8M,能夠減少訪問磁碟的次數,提高檔案讀取效能;
FileInputStream 的子類。 實現了裝飾設計模式!
BufferedInputStream沒有無參構造方法,它必須傳入一個InputStream(一般是FileInputStream),來一起使用,以提高讀寫效率。
構造方法:

1、BufferInputStream(InputStream in)// 建立一個 BufferedInputStream 並儲存其引數,即輸入流 in,以便將來使用。
   建立一個內部緩衝區陣列並將其儲存在 buf 中,該buf的大小預設為8192
 2、BufferedInputStream(InputStream in, int size//建立具有指定緩衝區大小的 BufferedInputStream 並儲存其引數,即輸入流 in,以便將來使用。
    建立一個長度為 size 的內部緩衝區陣列並將其儲存在 buf 中。
  • BufferedOutputStream

帶緩衝區的輸出流,能夠提高檔案的寫入效率。實現了裝飾設計模式!

BufferedOutputStream沒有無參構造方法,它必須傳入一個OutputStream(一般是FileOutputStream),來一起使用,以提高讀寫效率。
構造方法:

1、BufferOutputStream(**OutputStream outs**)// 建立一個 BufferedInputStream 並儲存其引數,即輸出流outs,將資料寫入指定的基本輸入流中。
    2、BufferedOutputStream(OutputStream outs, int size//建立具有指定緩衝區大小的 BufferedOutputStream ,即輸出流outs,將資料寫入指定的基本輸入流中 。

第一次寫部落格,寫的不好請輕噴!很多都是百度的,所有還是也會有不理解的,大佬們如有好的意見,可以提出來。畢竟是個菜鳥!