自从业至今,文件上传与IO流之类的调用,一直是理解比较模糊的地方,大多就这网上搜到的资料抄抄改改草草了事,内部原理一直不甚了解,今日咱们经过Spring的CommonsMultipartResolver的工具类一探文件上传的秘密;java
1.首先咱们先看看CommonsMultipartResolver自己:缓存
截图为CommonsMultipartResolver类的继承及接口实现关系:ide
a)咱们首先看看感受最没有关系的ServletContextAware,CommonsMultipartResolver实现了setServletContext方法,当没有指定临时的上传路径时,将上传的文件保存到ServletContext默认的位置;工具
@Override public void setServletContext(ServletContext servletContext) { if (!isUploadTempDirSpecified()) { getFileItemFactory().setRepository(WebUtils.getTempDir(servletContext)); } }
b)咱们再来看看MultipartResolver接口:post
CommonsMultipartResolver实现了截图中的三个方法,三个方法的源代码能够本身去查看,简单的说下方法的功能:this
resolveMultipart将HttpServletRequest转化为MultipartHttpServletRequest,将里面的FileItem不是表单字段的对象转换为MultipartFile;
@Override public MultipartHttpServletRequest resolveMultipart(final HttpServletRequest request) throws MultipartException { Assert.notNull(request, "Request must not be null"); if (this.resolveLazily) { return new DefaultMultipartHttpServletRequest(request) { @Override protected void initializeMultipart() { MultipartParsingResult parsingResult = parseRequest(request); setMultipartFiles(parsingResult.getMultipartFiles()); setMultipartParameters(parsingResult.getMultipartParameters()); setMultipartParameterContentTypes(parsingResult.getMultipartParameterContentTypes()); } }; } else { MultipartParsingResult parsingResult = parseRequest(request); return new DefaultMultipartHttpServletRequest(request, parsingResult.getMultipartFiles(), parsingResult.getMultipartParameters(), parsingResult.getMultipartParameterContentTypes()); } }
isMultipart(HttpServletRequest request)判断HttpServletRequest请求方式是否为post方式,content-type中是否以multipart/开头;编码
cleanupMultipart(MultipartHttpServletRequest request)将请求中的FileItem删除;spa
c)最后来看看抽象类CommonsFileUploadSupport,咱们比较经常使用的是MultipartParsingResult parseRequest(HttpServletRequest request)这个方法。code
2.CommonsMultipartResolver过程当中涉及到的类:orm
a)MultipartFile:在请求头为multiti/form-data时,request被转换为multipartRequest,FileItem皆为MultiPartFile;
b)FileItem:判断一个文件是否为formfield;
c)DiskFileItem:继承自FileItem,默认的字符集为ISO-8859-1;
c)FileUpload:能够设置文件大小以及文件的编码格式;
d)FileItemFactory:FileItem的建立工厂,根据fieldName,contenType,等字段建立一个FileItem;
e)DiskFileItemFactory:实现FileItemFactory,有默认的文件缓存内存,为10k大小,当上传文件大小超过默认的10k时保存到默认的临时目录中;
3.Spring文件上传的过程总结:
HttpServletRequest =>MultipartHttpServletRequest =>获取MultipartFile集合