遇到一個項目中寫的過濾器有些不明白爲什麼那麼寫,其實就是以下的第二部分不理解造成的
二、 使用servlet時:多部件表單上傳對servlet取值問題
1) request.getParameter("..."),這個方法在表單爲multiparty/form-data中取不到值
2) 但是我們可以使用 ServletInputStream request.getInputStream();來獲取流信息
過濾器代碼MyFilter:
package com.syb.webapp.common.filter; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import com.syb.core.util.StringUtil; /** * * @author sun * * tcl */ public class MyFilter implements Filter{ @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { String contentType = request.getContentType(); if(!StringUtil.isEmpty(contentType) && contentType.contains("multipart/form-data")) { chain.doFilter(request, response); return; } if(request instanceof HttpServletRequest) { request=new MyHttpServlerRequestWrapper((HttpServletRequest)request); } chain.doFilter(request, response); } @Override public void destroy() { } }
MyHttpServlerRequestWrapper:
package com.syb.webapp.common.filter; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.mock.web.DelegatingServletInputStream; import com.alibaba.fastjson.JSON; /** * * @author sun * * tcl */ public class MyHttpServlerRequestWrapper extends HttpServletRequestWrapper{ public static Logger logger=LoggerFactory.getLogger(MyHttpServlerRequestWrapper.class); private String body=null; private HttpServletRequest request; public MyHttpServlerRequestWrapper(HttpServletRequest request) { super(request); this.request=request; } @Override public ServletInputStream getInputStream() throws IOException { if(body!=null) { final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes()); return new DelegatingServletInputStream(byteArrayInputStream); //此方法作用? } StringBuilder stringBuilder=new StringBuilder(); InputStream inputStream=null; try { inputStream=request.getInputStream(); } catch (Exception e) { logger.error("Error reading the request body…", e); } if(inputStream!=null) { try { BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(inputStream)); char[] charBuffer=new char[1024]; int read; while((read=bufferedReader.read(charBuffer))>0) { stringBuilder.append(charBuffer, 0, read); } } catch (Exception e) { logger.error("Fail to read input stream", e); } }else { stringBuilder.append(""); } body=stringBuilder.toString(); final ByteArrayInputStream byteArrayInputStream=new ByteArrayInputStream(body.getBytes()); return new DelegatingServletInputStream(byteArrayInputStream); } public String getRequestParam() { if("GET".equals(this.getMethod())) { return JSON.toJSONString(getParameterMap()); } if("POST".equals(this.getMethod())) { String contentType = this.getContentType(); if(contentType.contains("applycation/json")) { return this.body; } if(contentType.contains("application/x-www-form-urlencoded")) { return JSON.toJSONString(getParameterMap()); } } return null; } }
以下內容轉自:http://blog.csdn.net/u011278387/article/details/50839034
一、上傳對錶單的要求
1) 表單的提交方式 :"method=post"
2) 表單的類型 :enctype="multipart/form-data"
3) 上傳表單的文件項:<input type="file" name="xx" /> //其中名字是必須要的
例如: <h1>上傳</h1>
<h2><font color="red"></font></h2>
<form action="" method="post" enctype="multipart/form-data"/>
<p>用戶名:<input name="userName" type="text"/></p>
<p>文件:<input name="xx" type="file"/></br></p>
<p><input type="submit" value="上傳"/></p>
</form>
二、 使用servlet時:多部件表單上傳對servlet取值問題
1) request.getParameter("..."),這個方法在表單爲multiparty/form-data中取不到值
2) 但是我們可以使用 ServletInputStream request.getInputStream();來獲取流信息
三、 多部件表單與普通表單的結構
1) 普通表單項結構 1個頭:content-Disposition,包含name="XXX" 即表單的名字, 表單體就是表單的值
2) 多部件表單普通表單結構 含有2個頭
*content-Disposition,包含name="xx",filname="上傳文件的路徑";
*content-type: 指上傳的文件類型,如上傳的是圖片的話格式則爲:image/jpeg
四、上傳的組件(這裏介紹2種)
1、使用apache-commons-fileupload 上傳*使用apache-commons-fileupload 上傳
*使用springmvc下的spring-webmvc (MultipartFile )上傳
1) commons-fileupload
*需要的jar(網上可以下載)
commons-fileupload
要使用流所以需要commons-io.jar;
2)上傳三步
*工廠:DiskFileItemFactory
*解析器:ServletFileUpload
*表單項:FileItem
3)相關代碼
*創建工廠
DiskFileItemFactory fac = new DiskFileItemFactory();
*創建解析器
ServletFileUpLoad sfp = new ServletFileUpLoad(fac);
*使用解析器 獲取FileItem 集合 List<FileItem> items = sfp.parseRequest(reques);
*看下 FileItem的方法
String filename = file.getName(); //文件名稱
String getFileName(); //返回當前表單項的名稱
String fileStr = file.getString(String charset); //返回表單的值;
long fileSize = file.getSize(); //文件的字節數
InputStream in = file.getInputStream(); //文件的對應輸入流
void write(file destFile); //將文件保存到指定的目錄
代碼例子:
request.setCharacterEncoding("utf-8"); //編碼
//創建工廠
DiskFileItemFactory factory = new DiskFileItemFactory();
//創建解析器
ServletFileUpload sfl = new ServletFileUpload(factory);
try {
//解析
List<FileItem> im = sfl.parseRequest(request);
FileItem f1 = im.get(0);
System.out.println("多部件表單項的文件:"+f1.getFieldName()
+"---名稱:"+f1.getName()+"文件大小:"+f1.getSize());
try {
//寫往磁盤(也可以寫到服務器的相應地址)
f1.write(new File("e:\\photo\\cc.jpg"));
} catch (Exception e) {
e.printStackTrace();
}
} catch (FileUploadException e) {
e.printStackTrace();
}
-------------------------------------------
五、上傳的細節2、使用MultipartFile
1) 由於Post一個包含文件上傳的Form會以multipart/form-data請求發送給服務 器,必須明確告訴轉發器(DispatcherServlet)如何處理MultipartRequest。首先在項目 配置文件中聲明一個MultipartResolver:
2) xml 代碼
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 設置上傳文件的最大尺寸爲1MB(也可以不配置而在代碼中限制上傳的文件大小) -->
<property name="maxUploadSize">
<value>1048576</value>
</property>
</bean>
3)、上傳步驟
*請求轉化爲多部件的請求
MultipartHttpServletRequest mulReq= (MultipartHttpServletRequest) request;
*獲取
MultipartFile mfile= mulReq.getFile(“多部件表單值的name”);
*寫入到相應的目錄
mfile.transferTo(new File(path));
4)、代碼例子:
//轉化request
MultipartHttpServletRequest mulReq= (MultipartHttpServletRequest) request;
//獲取上傳表單的name值
String picName = request.getParameter(“picName”);
//解析爲多部件文件
MultipartFile mfile = mulReq.getFile(picName);
//僅僅允許圖片格式
List<String> fileTypes = new ArrayList<String>();
fileTypes.add("jpg");
fileTypes.add("jpeg");
fileTypes.add("bmp");
fileTypes.add("gif");
fileTypes.add("png");
//取得原文件名稱
String orifilename = mfile.getOriginalFilename();
//獲取擴展名
String extensionName=orifilename.substring(orifilename.lastIndexOf(".")+1);
//校驗擴展名
if ( fileTypes.contains(extensionName.toLowerCase())) {
//限制圖片的大小
if(file.getSize() <= 5 * 1024*1024){
mfile.transferTo(new File(path));
}
}
--------------------------------------------
1、文件保存在項目的路徑
*文件保存可以在web-inf下(安全問題)其他目錄下可能被注入非法程序)
*上傳的文件保存webRoot下(因爲很多其他的項目都可能要用到上傳的文件)
2、上傳文件格式和大小:
*要求上傳的文件格式爲jpg,就不能上傳其他格式
上傳的時候就必須要限制上傳的文件類型,最好的做法是在前端和後臺都做下校驗。
*上傳文件的大小需要按要求做限制
3、文件名稱問題:
*上傳文件出現重名,所以需要我們爲文件加個前綴,前綴不能重複。可以是uuid (UUID uuid = UUID.randomUUID();)或者時間(System.currentTimeMillis())
*上傳文件亂碼問題
可以使用這個request.setCharacterEncoding("utf-8");
4、文件目錄
目錄打撒 一個目錄下不能存放太多的文件,不同的上傳功能目錄應該歸類存放。
5、緩存大小與臨時目錄(主要針對大文件上傳的)。
Common-FileUpload 中可以設置緩存大小和臨時目錄(默認是10k)
方法:DiskFileItemFactory(int sizeThreshold, File repository)
sizeThreshold爲定義的緩存大小,repository爲緩存目錄
如 DiskFileItemFactory fa = new DiskFileItemFactory(2*1024, new File(“F:/temp”));