common-fileUpload和 Spring中MultipartHttpServletRequest實現文件上傳、以及過濾器的問題

遇到一個項目中寫的過濾器有些不明白爲什麼那麼寫,其實就是以下的第二部分不理解造成的

二、 使用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)

*使用apache-commons-fileupload 上傳

*使用springmvc下的spring-webmvc (MultipartFile )上傳

 1、使用apache-commons-fileupload 上傳

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”));



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章