實現文件的下載功能

 下載方法說明:

下載的常用 API 說明:
response.getOutputStream();
servletContext.getResourceAsStream();
servletContext.getMimeType();
response.setContentType();

response.setHeader("Content-Disposition", "attachment; fileName=1.jpg");

這個響應頭告訴瀏覽器。這是需要下載的。而 attachment 表示附件,也就是下載的一個文件。fileName=後面,表示下載的文件名。

完成上面的兩個步驟,下載文件是沒問題了。但是如果我們要下載的文件是中文名的話。你會發現,下載無法正確

顯示出正確的中文名。

原因是在響應頭中,不能包含有中文字符,只能包含 ASCII 碼。文件下載示例:

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException {
        // 1、獲取要下載的文件名
        String downloadFileName = "2.jpg";
        // 2、讀取要下載的文件內容 (通過 ServletContext 對象可以讀取)
        ServletContext servletContext = getServletContext();
        // 獲取要下載的文件類型
        String mimeType = servletContext.getMimeType("/file/" + downloadFileName);
        System.out.println("下載的文件類型:" + mimeType);
        // 4、在回傳前,通過響應頭告訴客戶端返回的數據類型
        resp.setContentType(mimeType);
        // 5、還要告訴客戶端收到的數據是用於下載使用(還是使用響應頭)
        // Content-Disposition 響應頭,表示收到的數據怎麼處理
        // attachment 表示附件,表示下載使用
        // filename= 表示指定下載的文件名
        resp.setHeader("Content-Disposition", "attachment; filename=" +downloadFileName);
        /**
         * /斜槓被服務器解析表示地址爲 http://ip:prot/工程名/ 映射 到代碼的 Web 目錄
        */
        InputStream resourceAsStream = servletContext.getResourceAsStream("/file/" +downloadFileName);
        // 獲取響應的輸出流
        OutputStream outputStream = resp.getOutputStream();
        // 3、把下載的文件內容回傳給客戶端
        // 讀取輸入流中全部的數據,複製給輸出流,輸出給客戶端
        IOUtils.copy(resourceAsStream,outputStream);
    }

 

附件中文名亂碼問題解決方案:

方案一:URLEncoder 解決 IE 和谷歌瀏覽器的 附件中文名問題。

如果客戶端瀏覽器是 IE 瀏覽器 或者 是谷歌瀏覽器。我們需要使用 URLEncoder 類先對中文名進行 UTF-8 的編碼操作。
因爲 IE 瀏覽器和谷歌瀏覽器收到含有編碼後的字符串後會以 UTF-8 字符集進行解碼顯示。
// 把中文名進行 UTF-8 編碼操作。
String str = "attachment; fileName=" + URLEncoder.encode("中文.jpg", "UTF-8");
// 然後把編碼後的字符串設置到響應頭中
response.setHeader("Content-Disposition", str);
 

方案二:BASE64 編解碼 解決 火狐瀏覽器的附件中文名問

如果客戶端瀏覽器是火狐瀏覽器。 那麼我們需要對中文名進行 BASE64 的編碼操作。

這時候需要把請求頭 Content-Disposition: attachment; filename=中文名

編碼成爲:Content-Disposition: attachment; filename==?charset?B?xxxxx?==?charset?B?xxxxx?= 現在我們對這段內容進行一下說明。

=? 表示編碼內容的開始

charset 表示字符集

B 表示 BASE64 編碼

xxxx 表示文件名 BASE64 編碼後的內容

?= 表示編碼內容的結束

BASE64 編解碼操作:

public static void main(String[] args) throws Exception {

        String content = "這是需要 Base64 編碼的內容";
        // 創建一個 Base64 編碼器
        BASE64Encoder base64Encoder = new BASE64Encoder();
        // 執行 Base64 編碼操作
        String encodedString = base64Encoder.encode(content.getBytes("UTF-8"));
        System.out.println( encodedString );
        // 創建 Base64 解碼器
        BASE64Decoder base64Decoder = new BASE64Decoder();
        // 解碼操作
        byte[] bytes = base64Decoder.decodeBuffer(encodedString);
        String str = new String(bytes, "UTF-8");
        System.out.println(str);

    }

因爲火狐使用的是 BASE64 的編解碼方式還原響應中的漢字。所以需要使用 BASE64Encoder 類進行編碼操作。

 
// 使用下面的格式進行 BASE64 編碼後
String str = "attachment; fileName=" + "=?utf-8?B?"
            + new BASE64Encoder().encode("中文.jpg".getBytes("utf-8")) + "?=";
// 設置到響應頭中
response.setHeader("Content-Disposition", str);

那麼我們如何解決上面兩種不同編解碼方式呢。我們只需要通過判斷請求頭中 User-Agent 這個請求頭攜帶過來的瀏覽器信息即可判斷出是什麼瀏覽器。如下:

 
String ua = request.getHeader("User-Agent");
// 判斷是否是火狐瀏覽器
if (ua.contains("Firefox")) {
    // 使用下面的格式進行 BASE64 編碼後
    String str = "attachment; fileName=" + "=?utf-8?B?"
                + new BASE64Encoder().encode("中文.jpg".getBytes("utf-8")) + "?=";
    // 設置到響應頭中
    response.setHeader("Content-Disposition", str);
} else {
    // 把中文名進行 UTF-8 編碼操作。
    String str = "attachment; fileName=" + URLEncoder.encode("中文.jpg", "UTF-8");
    // 然後把編碼後的字符串設置到響應頭中
    response.setHeader("Content-Disposition", str);
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章