自從業至今,文件上傳與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集合