文件下載需求:
1. 頁面顯示超鏈接
2. 點擊超鏈接后彈出下載提示框
3. 完成圖片文件下載
分析過程:
1. 超鏈接指向的資源如果能夠被瀏覽器解析,則在瀏覽器中展示,如果不能解析,則彈出下載提示框。不滿足需求
2. 任何資源都必須彈出下載提示框
3. 使用響應頭設置資源的打開方式:
content-disposition:attachment;filename=xxx
步驟:
1. 定義頁面,編輯超鏈接href屬性,指向Servlet,傳遞資源名稱filename
2. 定義Servlet
1. 獲取文件名稱
2. 使用字節輸入流加載文件進內存
3. 指定response的響應頭: content-disposition:attachment;filename=xxx
4. 將數據寫出到response輸出流
代碼實現:
下載頁面:
1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="UTF-8">
5 <title>文件下載</title>
6 </head>
7 <body>
8
9
10 <a href="/day13/img/狐狸.jpg">圖片1</a>
11
12 <a href="/day13/img/2.jpg">圖片2</a>
13
14 <a href="/day13/img/1.avi">視頻</a>
15 <hr>
16
17
18 <a href="/day13/downloadservlet?filename=狐狸.jpg">圖片1</a>
19
20 <a href="/day13/downloadservlet?filename=2.jpg">圖片2</a>
21
22 <a href="/day13/downloadservlet?filename=1.avi">視頻</a>
23
24
25
26
27 </body>
28 </html>
DownLoadServlet 類
1 import javax.servlet.ServletContext; 2 import javax.servlet.ServletException; 3 import javax.servlet.ServletOutputStream; 4 import javax.servlet.annotation.WebServlet; 5 import javax.servlet.http.HttpServlet; 6 import javax.servlet.http.HttpServletRequest; 7 import javax.servlet.http.HttpServletResponse; 8 import java.io.FileInputStream; 9 import java.io.IOException; 10
11 @WebServlet("/downloadservlet") 12 public class downloadservlet extends HttpServlet { 13 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 14 //1獲取請求參數,文件名稱
15 String filename = request.getParameter("filename"); 16
17 //2使用字節輸入流加載文件進內存 18 // 2.1 找文件服務器路徑
19 ServletContext servletContext = this.getServletContext(); 20 String realPath = servletContext.getRealPath("/img/" + filename); 21
22 //2.2 使用字節流關聯
23 FileInputStream fis = new FileInputStream(realPath); 24
25 //3 設置 response 的響應頭 26 // 3.1 設置響應頭類型:content-type
27 String mimeType = servletContext.getMimeType(filename); 28 response.setHeader("content-type",mimeType); 29 // 3.2 設置響應頭打開方式:content-disposition
30
31 response.setHeader("content-disposition","attachment;filename="+filename); 32
33
34 // 4. 將輸入流的數據寫出到輸出流中
35 ServletOutputStream sos = response.getOutputStream(); 36
37 byte[] buff = new byte[1024*8]; 38 int len = 0; 39
40 while((len = fis.read(buff)) != -1) { 41 sos.write(buff,0,buff.length); 42 } 43
44 // 關閉流對象
45 fis.close(); 46 } 47
48 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 49 this.doPost(request, response); 50 } 51 }
上面的案例中發現,當下載的文件名字是中文的時候,下載的時候會出現亂碼。
文件名中文亂碼問題
解決思路:
(1)獲取客戶端使用的瀏覽器版本信息
(2)根據不同的版本信息,設置 filename 的編碼方式不同
編碼工具類:
使用 Base64 編碼,需要導入 commons-codec-1.13.jar 包。
1 package cn.itcast.download; 2
3
4 import org.apache.commons.codec.binary.Base64; 5
6 import java.io.UnsupportedEncodingException; 7 import java.net.URLEncoder; 8
9
10 public class DownLoadUtils { 11
12 public static String getFileName(String agent, String filename) throws UnsupportedEncodingException { 13 if (agent.contains("MSIE")) { 14 // IE瀏覽器
15 filename = URLEncoder.encode(filename, "utf-8"); 16 filename = filename.replace("+", " "); 17 } else if (agent.contains("Firefox")) { 18 Base64 base64Encoder = new Base64(); 19 // 火狐瀏覽器 20 //BASE64Encoder base64Encoder = new BASE64Encoder();
21 filename = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?="; 22 } else { 23 // 其它瀏覽器
24 filename = URLEncoder.encode(filename, "utf-8"); 25 } 26 return filename; 27 } 28 }
DownLoadServlet 類(改進):
1 package cn.itcast.download; 2
3 import javax.servlet.ServletContext; 4 import javax.servlet.ServletException; 5 import javax.servlet.ServletOutputStream; 6 import javax.servlet.annotation.WebServlet; 7 import javax.servlet.http.HttpServlet; 8 import javax.servlet.http.HttpServletRequest; 9 import javax.servlet.http.HttpServletResponse; 10 import java.io.FileInputStream; 11 import java.io.IOException; 12
13 @WebServlet("/downloadservlet") 14 public class downloadservlet extends HttpServlet { 15 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 16 //1獲取請求參數,文件名稱
17 String filename = request.getParameter("filename"); 18
19 //2使用字節輸入流加載文件進內存 20 // 2.1 找文件服務器路徑
21 ServletContext servletContext = this.getServletContext(); 22 String realPath = servletContext.getRealPath("/img/" + filename); 23
24 //2.2 使用字節流關聯
25 FileInputStream fis = new FileInputStream(realPath); 26
27 //3 設置 response 的響應頭 28 // 3.1 設置響應頭類型:content-type
29 String mimeType = servletContext.getMimeType(filename); 30 response.setHeader("content-type",mimeType); 31 // 3.2 設置響應頭打開方式:content-disposition 32
33 // 3.3 解決中文文件名問題 34 // 1 獲取 user-agent 請求頭
35 String agent = request.getHeader("user-agent"); 36 // 2 使用工具類方法編碼文件即可
37 filename = DownLoadUtils.getFileName(agent, filename); 38
39 response.setHeader("content-disposition","attachment;filename="+filename); 40
41
42 // 4. 將輸入流的數據寫出到輸出流中
43 ServletOutputStream sos = response.getOutputStream(); 44
45 byte[] buff = new byte[1024*8]; 46 int len = 0; 47
48 while((len = fis.read(buff)) != -1) { 49 sos.write(buff,0,buff.length); 50 } 51
52 // 關閉流對象
53 fis.close(); 54 } 55
56 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 57 this.doPost(request, response); 58 } 59 }