下載方法說明:
下載的常用 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);
}