common-fileUpload和 Spring中MultipartHttpServletRequest实现文件上传、以及过滤器的问题

http 同时被 2 个专栏收录
2 篇文章 0 订阅
1 篇文章 0 订阅

遇到一个项目中写的过滤器有些不明白为什么那么写,其实就是以下的第二部分不理解造成的

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



  • 1
    点赞
  • 0
    评论
  • 1
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值