創建時間:6.19 & 6.24
1.案例-完成文件下載
1) 什么情況下會文件下載?
瀏覽器不能解析的文件就下載
*使用a標簽直接指向服務器上的資源
2)什么情況下需要在服務端編寫文件下載的代碼?
理論上,瀏覽器可以解析的代碼需要編寫文件下載代碼
實際開發中,只要是下載的文件都編寫文件下載代碼
文件下載的實質就是文件拷貝,將文件從服務器端拷貝到瀏覽器端。所以文件下載需要IO技術將服務器端的文件使用InputStream讀取到,在使用 ServletOutputStream寫到response緩沖區中
代碼如下:
上述代碼可以將圖片從服務器端傳輸到瀏覽器,但瀏覽器直接解析圖片顯示在頁面上,而不是提供下載,我們需要設置兩個響應頭,告知瀏覽器文件的類型和文件的打開方式。
1)告知瀏覽器文件的類型:response.setContentType(文件的MIME類型);
2)告示瀏覽器文件的打開方式是下載:
response.setHeader("Content-Disposition","attachment;filename=文件名稱");
代碼如下:
*客戶端不是根據文件擴展名來區分文件的類型,而是通過文件的MIME類型(在tomcat的web.xml中對extension進行MIME的映射)
但是,如果下載中文文件,頁面在下載時會出現中文亂碼或不能顯示文件名的情況, 原因是不同的瀏覽器默認對下載文件的編碼方式不同,ie是UTF-8編碼方式,而火狐瀏覽器是Base64編碼方式。所里這里需要解決瀏覽器兼容性問題,解決瀏覽器兼容 性問題的首要任務是要辨別訪問者是ie還是火狐(其他),通過Http請求體中的一個屬性可以辨別
解決亂碼方法如下(不要記憶--了解):
其中agent就是請求頭User-Agent的值
1 if (agent.contains("MSIE")) { 2 3 // IE瀏覽器 4 5 filename = URLEncoder.encode(filename, "utf-8"); 6 7 filename = filename.replace("+", " "); 8 9 } else if (agent.contains("Firefox")) { 10 11 // 火狐瀏覽器 12 13 BASE64Encoder base64Encoder = new BASE64Encoder(); 14 15 filename = "=?utf-8?B?" 16 17 + base64Encoder.encode(filename.getBytes("utf-8")) + "?="; 18 19 } else { 20 21 // 其它瀏覽器 22 23 filename = URLEncoder.encode(filename, "utf-8"); 24 25 }
完整代碼:見WEB14代碼DownloadServlet2.java
1 package com.itheima.content; 2 3 4 5 import java.io.FileInputStream; 6 7 import java.io.IOException; 8 9 import java.io.InputStream; 10 11 import java.net.URLEncoder; 12 13 14 15 import javax.servlet.ServletException; 16 17 import javax.servlet.ServletOutputStream; 18 19 import javax.servlet.http.HttpServlet; 20 21 import javax.servlet.http.HttpServletRequest; 22 23 import javax.servlet.http.HttpServletResponse; 24 25 26 27 import sun.misc.BASE64Encoder; 28 29 30 31 public class DownLoadServlet2 extends HttpServlet { 32 33 34 35 protected void doGet(HttpServletRequest request, HttpServletResponse response) 36 37 throws ServletException, IOException { 38 39 40 41 //*******文件名稱是中文的下載******* 42 43 44 45 46 47 //獲得要下載的文件的名稱 48 49 String filename = request.getParameter("filename");//????.jpg 50 51 //解決獲得中文參數的亂碼----下節課講 52 53 filename = new String(filename.getBytes("ISO8859-1"),"UTF-8");//美女.jpg 54 55 56 57 58 59 //獲得請求頭中的User-Agent 60 61 String agent = request.getHeader("User-Agent"); 62 63 //根據不同瀏覽器進行不同的編碼 64 65 String filenameEncoder = ""; 66 67 if (agent.contains("MSIE")) { 68 69 // IE瀏覽器 70 71 filenameEncoder = URLEncoder.encode(filename, "utf-8"); 72 73 filenameEncoder = filenameEncoder.replace("+", " "); 74 75 } else if (agent.contains("Firefox")) { 76 77 // 火狐瀏覽器 78 79 BASE64Encoder base64Encoder = new BASE64Encoder(); 80 81 filenameEncoder = "=?utf-8?B?" 82 83 + base64Encoder.encode(filename.getBytes("utf-8")) + "?="; 84 85 } else { 86 87 // 其它瀏覽器 88 89 filenameEncoder = URLEncoder.encode(filename, "utf-8"); 90 91 } 92 93 94 95 96 97 98 99 //要下載的這個文件的類型-----客戶端通過文件的MIME類型去區分類型 100 101 response.setContentType(this.getServletContext().getMimeType(filename)); 102 103 //告訴客戶端該文件不是直接解析 而是以附件形式打開(下載)----filename="+filename 客戶端默認對名字進行解碼 104 105 response.setHeader("Content-Disposition", "attachment;filename="+filenameEncoder); 106 107 108 109 //獲取文件的絕對路徑 110 111 String path = this.getServletContext().getRealPath("download/"+filename); 112 113 //獲得該文件的輸入流 114 115 InputStream in = new FileInputStream(path); 116 117 //獲得輸出流---通過response獲得的輸出流 用於向客戶端寫內容 118 119 ServletOutputStream out = response.getOutputStream(); 120 121 //文件拷貝的模板代碼 122 123 int len = 0; 124 125 byte[] buffer = new byte[1024]; 126 127 while((len=in.read(buffer))>0){ 128 129 out.write(buffer, 0, len); 130 131 } 132 133 134 135 in.close(); 136 137 //out.close(); 138 139 140 141 } 142 143 144 145 protected void doPost(HttpServletRequest request, HttpServletResponse response) 146 147 throws ServletException, IOException { 148 149 doGet(request, response); 150 151 } 152 153 }
response細節點:
1)response獲得的流不需要手動關閉,web容器(tomcat)會幫助我們關閉
2)getWriter和getOutputStream不能同時調用
驗證碼案例:不用掌握生成驗證碼,只要掌握html頁面里怎么改