1. 實現一個加強的HttpServletResponse類,須要繼承javax.servlet.http.HttpServletRequestWrapper類,經過重寫本身須要加強的方法來實現(這種模式就叫作裝飾者模式),使用該加強類在加上過濾器就能夠實現無編碼轉換處理代碼。javascript
public class MyRequest extends HttpServletRequestWrapper{ private HttpServletRequest req; public MyRequest(HttpServletRequest request) { super(request); req=request; } @Override public String getParameter(String name) { //解決編碼問題,不管是post仍是get請求,都不須要在業務代碼中對編碼再處理 String method=req.getMethod(); if("get".equalsIgnoreCase(method)){ try { String str=req.getParameter(name); byte[] b=str.getBytes("iso8859-1"); String newStr=new String(b, "utf-8"); return newStr; } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } }else if("post".equalsIgnoreCase(method)){ try { req.setCharacterEncoding("utf-8"); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } } //絕對不能刪除此行代碼,由於此行代碼返回的就是編碼以後的數據 return super.getParameter(name); } }
在過濾器中應用html
public class FilterTest4 implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException {} @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { //生成加強的HttpServletRequest對象 HttpServletRequest req=(HttpServletRequest) request; MyRequest myReq=new MyRequest(req); //將加強的HttpServletRequest對象傳入過濾器執行鏈中,在後面傳入的request對象都會是加強的HttpServletRequest對象 chain.doFilter(myReq, response); } @Override public void destroy() {} }
1. JavaWeb中實現文件上傳:java
<html> <head> <title>My JSP 'upload.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> </head> <body> <form action="" method="post" enctype="multipart/form-data"> <input type="text" name="name"> 請選擇文件:<input type="file" name="upload"> <input type="submit" value="上傳"> </form> </body> </html>
import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.List; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.FileUploadException; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; public class UploadServlet extends HttpServlet{ @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { /** * 1. 建立磁盤文件項工廠類 DiskFileItemFactory * 2. 建立核心解析Request類 ServletFileUpload * 3. 開始解析Request對象中的數據,並返回一個List集合 * 4. List中包含表單中提交的內容 * 5. 遍歷集合,獲取內容 */ DiskFileItemFactory fac=new DiskFileItemFactory(); ServletFileUpload upload=new ServletFileUpload(fac); upload.setHeaderEncoding("utf-8");//防止中文的文件名亂碼 try { List<FileItem> fileItems = upload.parseRequest(req); for(FileItem item:fileItems){ //有多是普通文本項,好比<input type="text">標籤提交上來的字符串 //也有多是<input type="submit" value="上傳">上傳的文件 //文件項與普通項有不一樣的API來處理 //首先判斷是普通文本項仍是文件項, if(item.isFormField()){ //true表示普通文本項 //獲取文本項的name屬性值 String name=item.getFieldName(); //獲取對應的文本 String value=item.getString("utf-8");//防止中文亂碼 System.out.println(name+":"+value); }else{ //false表示文件項 //先獲取文件名稱 String name=item.getName(); //獲取文件項的輸入流 InputStream in=item.getInputStream(); //獲取服務器端文件存儲的目標磁盤路徑 String path=getServletContext().getRealPath("/upload"); System.out.println(path); //獲取輸出流,輸出到本地文件中 OutputStream out=new FileOutputStream(path+"/"+name); //寫入數據 int len=0; byte[] b=new byte[1024]; while((len=in.read(b))!=-1){ out.write(b,0,len); } in.close(); out.close(); } } } catch (FileUploadException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
注意:在文件上傳時,會將form表單的屬性enctype屬性值爲"multipart/form-data",當提交到服務端後,沒法使用 req.getParameter(name) 方法來獲取到內容,只有經過上面的方法來獲取文本項。算法
2. 文件上傳相關核心類:apache
//改進上面的文件上傳代碼,添加一個臨時文件 public class UploadServlet extends HttpServlet{ @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { DiskFileItemFactory fac=new DiskFileItemFactory(); fac.setSizeThreshold(1024*1024);//設置緩衝區爲1mb //設置臨時文件的本地磁盤存儲路徑 File repository=new File(getServletContext().getRealPath("/temp")); fac.setRepository(repository); ServletFileUpload upload=new ServletFileUpload(fac); upload.setHeaderEncoding("utf-8");//防止中文的文件名亂碼 try { List<FileItem> fileItems = upload.parseRequest(req); for(FileItem item:fileItems){ if(item.isFormField()){ String name=item.getFieldName(); String value=item.getString(); String value=item.getString("utf-8");//防止中文亂碼 System.out.println(name+":"+value); }else{ String name=item.getName(); InputStream in=item.getInputStream(); String path=getServletContext().getRealPath("/upload"); System.out.println(path); OutputStream out=new FileOutputStream(path+"/"+name); int len=0; byte[] b=new byte[1024]; while((len=in.read(b))!=-1){ out.write(b,0,len); } in.close(); out.close(); } } } catch (FileUploadException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
3. 實現多文件上傳(須要js技術):主要是更改jsp頁面,經過js代碼來添加多個文件進行上傳,服務器代碼無需更改瀏覽器
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" contentType="text/html; charset=utf-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'upload.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> </head> <body> <script type="text/javascript"> function run(){ var div=document.getElementById("divId"); div.innerHTML+= "<div><input type='file' name='upload'><input type='button' value='刪除' onclick='del(this)'></div>" } function del(presentNode){ var div=document.getElementById("divId"); div.removeChild(presentNode.parentNode); } </script> <div> 多文件上傳<br/> <form action="/Servlet/upload" method="post" enctype="multipart/form-data"> <input type="button" value="添加" onclick="run()"><br/> <div id="divId"> </div> <input type="submit" value="上傳"> </form> </div> </body> </html>
4. 關於文件上傳的一些問題:緩存
1. 傳統文件下載方式有超連接下載或者後臺程序下載兩種方式。經過超連接下載時,若是瀏覽器能夠解析,那麼就會直接打開,若是不能解析,就會彈出下載框;然後臺程序下載就必須經過兩個響應頭和一個文件的輸入流。服務器
2. 後臺程序下載:app
import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.OutputStream; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * @ClassName:DownLoadServlet * @Description:文件下載 * @author: * @date:2018年9月16日 */ public class DownLoadServlet extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { //獲取請求參數,知道要下載那個文件 String filename=req.getParameter("filename"); //設置響應頭 String contentType=getServletContext().getMimeType(filename);//依據文件名自動獲取對應的Content-Type頭 res.setContentType(contentType); res.setHeader("Content-Dispotition", "attachment;filename="+filename);//設置該頭,以附件形式打開下載 //獲取文件的輸入流 String path=getServletContext().getRealPath("/download")+"/"+filename; FileInputStream in=new FileInputStream(new File(path)); OutputStream out= res.getOutputStream(); byte[] b=new byte[1024]; int len=0; while((len=in.read(b))!=-1){ out.write(b,0,len); } in.close(); out.close(); } }