java源码 - SpringMVC(8)之 MultipartResolver

StandardServletMultipartResolver和CommonsMultipartResolver。前者使用了Servlet3.0标准的上传方式,后者使用了Apache的commons-fileupload。

1. StandardServletMultipartResolver

StandardServletMultipartResolver使用了Servlet3.0标准的上传方式,在Servlet3.0中上传文件非常简单,只需要调用request的getParts方法就可以获取所有上传的文件。

获取到Part后直接调用它到write(saveFileName)方法就可以将文件保存为以saveFileName为文件名的文件,也可以调用getInputStream获取InputStream。

public class StandardServletMultipartResolver implements MultipartResolver {

	private boolean resolveLazily = false;


	/**
	*设置在时是否惰性解决多部分请求
	*文件或参数访问。
	*
	默认为“false”,立即分解多部分元素,抛出
	*调用{@link #resolveMultipart}时对应的异常。
	*对于懒惰的多部分解析,将其切换为“true”,抛出解析异常
	*一旦应用程序试图获得多部分文件或参数。
	*/
	public void setResolveLazily(boolean resolveLazily) {
		this.resolveLazily = resolveLazily;
	}


	@Override
	public boolean isMultipart(HttpServletRequest request) {
		return StringUtils.startsWithIgnoreCase(request.getContentType(), "multipart/");
	}

	@Override
	public MultipartHttpServletRequest resolveMultipart(HttpServletRequest request) throws MultipartException {
		return new StandardMultipartHttpServletRequest(request, this.resolveLazily);
	}

	@Override
	public void cleanupMultipart(MultipartHttpServletRequest request) {
		if (!(request instanceof AbstractMultipartHttpServletRequest) ||
				((AbstractMultipartHttpServletRequest) request).isResolved()) {
			// To be on the safe side: explicitly delete the parts,
			// but only actual file parts (for Resin compatibility)
			try {
				for (Part part : request.getParts()) {
					if (request.getFile(part.getName()) != null) {
						part.delete();
					}
				}
			}
			catch (Throwable ex) {
				LogFactory.getLog(getClass()).warn("Failed to perform cleanup of multipart items", ex);
			}
		}
	}

}

resolveMultipart 方法返回了StandardMultipartHttpServletRequest:

public StandardMultipartHttpServletRequest(HttpServletRequest request, boolean lazyParsing)
			throws MultipartException {

		super(request);
		if (!lazyParsing) {
			parseRequest(request);
		}
	}
private void parseRequest(HttpServletRequest request) {
		try {
			Collection<Part> parts = request.getParts();
			this.multipartParameterNames = new LinkedHashSet<>(parts.size());
			MultiValueMap<String, MultipartFile> files = new LinkedMultiValueMap<>(parts.size());
			for (Part part : parts) {
				String headerValue = part.getHeader(HttpHeaders.CONTENT_DISPOSITION);
				ContentDisposition disposition = ContentDisposition.parse(headerValue);
				String filename = disposition.getFilename();
				if (filename != null) {
					if (filename.startsWith("=?") && filename.endsWith("?=")) {
						filename = MimeDelegate.decode(filename);
					}
					files.add(part.getName(), new StandardMultipartFile(part, filename));
				}
				else {
					this.multipartParameterNames.add(part.getName());
				}
			}
			setMultipartFiles(files);
		}
		catch (Throwable ex) {
			handleParseFailure(ex);
		}
	}

大概思路就是通过request的getParts方法获取所有Part,然后使用它们创建出File并保存到对应的属性;

再回过头来看isMultipart方法中首先判断是不是post请求,如果是则再检查contentType是不是以“multipart/”开头,如果也是则认为是上传请求。

cleanupMultipart方法删除了缓存。

2. CommonsMultipartResolver

CommonsMultipartResolver使用了commons-fileupload来完成具体的上传操作。

在CommonsMultipartResolver中,判断是不是上传请求的isMultipart,这将交给commons-fileupload的ServletFileUpload类完成

	@Override
	public boolean isMultipart(HttpServletRequest request) {
		return ServletFileUpload.isMultipartContent(request);
	}

实际处理request的方法是resolveMultipart:

	@Override
	public MultipartHttpServletRequest resolveMultipart(final HttpServletRequest request) throws MultipartException {
		Assert.notNull(request, "Request must not be null");
		if (this.resolveLazily) {
		//是懒处理,那么就使用DefaultMultipartHttpServletRequest
			return new DefaultMultipartHttpServletRequest(request) {
				@Override
				protected void initializeMultipart() {
					MultipartParsingResult parsingResult = parseRequest(request);
					setMultipartFiles(parsingResult.getMultipartFiles());
					setMultipartParameters(parsingResult.getMultipartParameters());
					setMultipartParameterContentTypes(parsingResult.getMultipartParameterContentTypes());
				}
			};
		}
		else {
		//如果不是,则先调用parseRequest方法来处理request
			MultipartParsingResult parsingResult = parseRequest(request);
			
			return new DefaultMultipartHttpServletRequest(request, parsingResult.getMultipartFiles(),
					parsingResult.getMultipartParameters(), parsingResult.getMultipartParameterContentTypes());
		}
	}

虽然有两种处理方法,但都是将Request转换为DefaultMultipartHttpServletRequest类型,而且都使用parseRequest方法进行处理。
这里我没有导入具体的包,所以感兴趣的可以导入commons包了解一下。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值