Servlet - 3.1下@MultipartConfig注解方式上传文件

Servlet3.0之前上传文件通常借助commons-fileupload-xxx.jar和commons-io-xxx.jar两个jar包,其中相关的API较多,写起来非常不便。而在Servlet3.0时,改进了部分API,可以通过@MultipartConfig注解以及相关的方法比较方便的进行文件上传。

 

一.常用的与文件上传相关的API与注意点:

1.HttpServletRequest提供的方法

  • Part getPart(String name):根据名称获取文件上传域
  • Collection<Part> getParts():获取所有的文件上传域

2.Part中常用的方法

  • String getContentType():获取上传文件的文件类型
  • long getSize():上传文件的大小
  • String getSubmittedFileName():上传文件的原始文件名
  • String getName():获取<input name="upload" ...>标签中name属性值
  • String getHeader(String name):获取请求头部
  • Collection<String> getHeaderNames():获取所有请求头部名称
  • InputStream getInputStream():获取上传文件的输入流
  • void write(String path):保存文件至服务器

3.表单enctype属性说明

在使用<input type="file" name="upload">标签时,需要设置enctype="multipart/form-data",指定表单数据的编码方式。enctype属性值说明:

  • application/x-www-form-urlencoded:默认编码方式,只处理表单中的value属性值,这种编码方式会将表单中的值处理成URL编码方式
  • multipart/form-data:以二进制流的方式处理表单数据
  • text/plain:当表单action属性为mailto:URL形式时比较方便,适用于直接通过表单发送邮件方式

4.@MultipartConfig注解属性说明

属性类型是否必需说明
maxFileSizelong 
maxRequestSizelong 
fileSizeThresholdint 
locationString 

 

 

二.测试文件上传

1.uploadUI.jsp

设置ectype属性为multipart/form-data才可上传文件

<form id="fileForm" action="${pageContext.request.contextPath}/file/upload" method="post" enctype="multipart/form-data">
	<table>
		<tr>
			<td>名称</td>
			<td><input type="text" name="name"> </td>
		</tr>
		<tr>
			<td>请选择文件</td>
			<td>
				<input type="file" name="upload"> 
				<input type="file" name="upload">
				<input type="file" name="upload2">
			</td>
		</tr>
		<tr>
			<td colspan="2">
				<input type="submit" value="上传">
			</td>
		</tr>
	</table>
</form>

2.FileServlet.java

方式一:使用@MultipartConfig注解

(1).处理文件上传的Servlet使用@MultipartConfig注解修饰;该Servlet主要完成访问上传页面以及处理文件上传,通过HttpServletRequest提供的getPart(String name)或getParts()方法获取到上传的文件,再使用Part相关的API获取文件信息以及完成上传。

(2).通过该注解提供的属性:maxFileSize、maxRequestSize等可以对上传文件大小、请求大小进行控制

@WebServlet(name="fileServlet", urlPatterns="/file/*")
@MultipartConfig(
		maxFileSize = 5*1024*1024
	)
public class FileServlet extends HttpServlet {
	private static final long serialVersionUID = 6956924658471003841L;

	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		
		String uri = request.getRequestURI();
		String methodName = uri.substring(uri.lastIndexOf("/") + 1);
		
		if (methodName.equals("uploadUI")) {// 上传页面
			uploadUI(request, response);
		} else if(methodName.equals("upload")){// 上传
			upload(request, response);
		}
	}
	
	@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}
	
	/**
	 * 文件上传页面
	 * @date 2017年5月1日
	 * @param request
	 * @param response
	 * @throws ServletException
	 * @throws IOException
	 * <p>Description:</p>
	 */
	public void uploadUI(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.getRequestDispatcher("/WEB-INF/jsp/file/uploadUI.jsp").forward(request, response);
	}
	
	/**
	 * 文件上传
	 * @date 2017年5月1日
	 * @param request
	 * @param response
	 * @throws ServletException
	 * @throws IOException
	 * <p>Description:</p>
	 */
	public void upload(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// 普通参数
		String name = request.getParameter("name");
		System.out.println("name:" + name);
		
		// 文件
		Part part = request.getPart("upload");
		this.uploadFile(part);
		
		// 所有部件
//		Collection<Part> parts = request.getParts();
//		if(parts != null && parts.size() > 0){
//			for(Part part : parts){
//				this.uploadFile(part);
//			}
//		}
		
	}
	
	/**
	 * 上传文件
	 * @date 2017年5月2日
	 * @param part
	 * <p>Description:</p>
	 */
	private void uploadFile(Part part) {
		try {
			if (part != null) {
				String submittedFileName = part.getSubmittedFileName();// 原文件名称,Servlet3.1提供
				if (submittedFileName != null && part.getSize() > 0) {
					// 获取上传文件信息
					System.out.println("文件类型:" + part.getContentType());// MIME类型
					System.out.println("文件大小:" + part.getSize());// 文件大小 字节
					System.out.println("SubmittedFileName:" + part.getSubmittedFileName());
					System.out.println("Name:" + part.getName());

					// 获取文件上传域信息
					Collection<String> headerNames = part.getHeaderNames();
					for (String headName : headerNames) {
						System.out.println("headName:" + headName + " --- value:" + part.getHeader(headName));
					}
					
					// 保存至服务器
					String basePath = this.getServletContext().getRealPath("/");
					String path = basePath + "/uploads/file/" + part.getSubmittedFileName();
					part.write(path);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

方式二:web.xml方式配置

使用web.xml方式配置时,需要在<servlet>中添加<multipart-config>标签用来标识该Servlet用于处理文件,否则getPart(name)会是null。该标签与@MultipartConfig注解作用一致,其中的对上传文件的控制所使用的属性也一样,可以根据实际需要配置。

<servlet>
  	<servlet-name>fileServlet</servlet-name>
  	<servlet-class>cn.edu.njit.servlet.FileServlet</servlet-class>
  	<multipart-config/>
</servlet>
<servlet-mapping>
  	<servlet-name>fileServlet</servlet-name>
  	<url-pattern>/file/*</url-pattern>
</servlet-mapping>

3.测试说明

(1).使用getPart(String name)方法

在使用request.getPart("upload")时,只会获取表单中所有标签name属性为"upload"中第一个出现的标签,可能是文件、普通元素,所以最好要先判断是否是文件。

(2).使用getParts()方法

使用该方法时,获取表单中所有标签,遍历返回的Collection<Part>集合类即可。其中,Part也是包含普通元素以及文件,需要判断一下再使用。

 

三.注

(1).对于要上传文件的Servlet,注解方式配置时,使用@MultipartConfig注解修饰;web.xml配置时,使用<multipart-config>标签标识,二者作用一致。

(2).Collection<Part> getParts()中,包含普通表单标签以及文件,需要判断Part是否是文件再进行对应的处理;Part getPart("xxx")匹配的是表单name属性为"xxx"中第一个标签

(3).对上传文件的控制可借助@MultipartConfig提供的属性,但提示不友好,直接报500错误,最好能捕获该异常给出相应的友好提示;也可在Servlet中通过Part提供的API对上传文件进行控制。

(4).在文件上传时,保存到服务器的文件一般不使用原来的文件名,为避免重复可使用java.util.UUID工具生成文件名;还可根据日期创建目录并保存文件,如当前日期为2017-5-4,则可保存为2017/5/4/aaabbbccc.txt。
 

demo代码:https://github.com/mytt-10566/servlet

 

 

 

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值