Java-上傳檔案Spring MultipartResolver 或者 ServletFileUpload
在Java開發過程中,如果我們想開發上傳功能,那麼有兩種方法可以解決:
使用Spring框架中的MultipartResolver 使用原生的程式碼ServletFileUpload 下面就簡單介紹下兩種方法如何使用:
1.Spring框架中的MultipartResolver:大體配置和使用程式碼如下
# 將如下xml放入到servlet.xml中: <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <property name="maxUploadSize" value="20000000" /> <!-- 上傳限制 20M --> </bean> # 然後在程式碼中這樣寫: @RequestMapping(value = "upload", method = RequestMethod.POST) public void upload(HttpServletRequest req, HttpServletResponse response, @RequestParam(value="file", required=true) MultipartFile file, )throws IOException { // 1. upload file, 獲取bytes內容 ByteArrayOutputStream bytes = new ByteArrayOutputStream(); IOUtils.copy(file.getInputStream(), bytes); byte[] byteArray = bytes.toByteArray();} # Html上傳頁面這樣寫: <form name="uploadForm" action="upload" method="POST" enctype="multipart/form-data" > <label>上傳檔案 </label><br/> <input type="file" name="file" size="100" style="width:300px;" /> <br /> <input type="submit" name="submit" value="submit"/> </form>
2.原生的程式碼ServletFileUpload:大體配置和使用程式碼如下(HTML同上Spring框架中的MultipartResolver)
@RequestMapping(value = "upload", method = RequestMethod.POST) public void upload(HttpServletRequest req, HttpServletResponse resp ) throws ServletException, IOException, FileUploadException{ boolean isMultipart = ServletFileUpload.isMultipartContent(req); HashMap<String, String> request = new HashMap<String, String>(); if (isMultipart) { DiskFileItemFactory factory = new DiskFileItemFactory(1024 * 1024 * 20, null); ServletFileUpload upload = new ServletFileUpload(factory); upload.setHeaderEncoding("UTF-8"); upload.setSizeMax(1024 * 1024 * 20); List<FileItem> fileItems = upload.parseRequest(req); Iterator<FileItem> iter = fileItems.iterator(); while (iter.hasNext()) { FileItem item = (FileItem) iter.next(); if (item.isFormField()) { String name = item.getFieldName(); String value = item.getString("UTF-8"); request.put(name, value); } else { byte[] filebytes = item.get(); if (StringUtils.isBlank(item.getName())) { continue; } request.put(item.getFieldName(), new String(filebyte, "utf-8")); } } } } 以上是簡單介紹如何使用上傳的兩種方法。這兩種方法既可以單一配置使用,也可以一起配置使用,但是再一 起使用的過程中會出現一個衝突的問題,下面是我再使用過程中遇到的一個問題和解決辦法。
1.問題描述:
如果同時使用了MultipartResolver 和ServletFileUpload,就會導致衝突使ServletFileUpload的方法獲取不到http資料,導致在iter.hasNext()返回false.然後整個迴圈就跳出去了。程式碼如下:
if (isMultipart) { DiskFileItemFactory factory = new DiskFileItemFactory(1024 * 1024 * 20, null); ServletFileUpload upload = new ServletFileUpload(factory); upload.setHeaderEncoding("UTF-8"); upload.setSizeMax(1024 * 1024 * 20); List<FileItem> fileItems = upload.parseRequest(req); Iterator<FileItem> iter = fileItems.iterator(); // 這裡獲取不到任何FileItem while (iter.hasNext()) { FileItem item = (FileItem) iter.next(); if (item.isFormField()) { String name = item.getFieldName(); String value = item.getString("UTF-8"); request.put(name, value); } else { byte[] filebytes = item.get(); if (StringUtils.isBlank(item.getName())) { continue; } request.put(item.getFieldName(), new String(filebyte, "utf-8")); } } } } 2.問題產生的原因: 整個問題產生的原因是Spring框架先呼叫了MultipartResolver 來處理http multi-part的請求,這裡http multipart的
請求已經消耗掉。後面又交給ServletFileUpload ,那麼ServletFileUpload 就獲取不到相應的multi-part請求。想快速解
決這個問題,解決方法是加入自己寫的multipartResolver,來單獨處理某些請求。這些請求需要特判。解決程式碼如下:
package example; import javax.servlet.http.HttpServletRequest; import org.springframework.web.multipart.commons.CommonsMultipartResolver; /** * @author */ public class MyMultipartResolver extends CommonsMultipartResolver { private String excludeUrls; private String[] excludeUrlArray; public String getExcludeUrls() { return excludeUrls; } public void setExcludeUrls(String excludeUrls) { this.excludeUrls = excludeUrls; this.excludeUrlArray = excludeUrls.split(","); } /** * 這裡是處理Multipart http的方法。如果這個返回值為true,那麼Multipart http body就會MyMultipartResolver 消耗掉.如果這裡返回false * 那麼就會交給後面的自己寫的處理函式處理例如剛才ServletFileUpload 所在的函式 * @see org.springframework.web.multipart.commons.CommonsMultipartResolver#isMultipart(javax.servlet.http.HttpServletRequest) */ @Override public boolean isMultipart(HttpServletRequest request) { for (String url: excludeUrlArray) { // 這裡可以自己換判斷 if (request.getRequestURI().contains(url)) { return false; } } return super.isMultipart(request); } } 然後在springmvc-servlet.xml中這樣寫: <bean id="multipartResolver" class="example.MyMultipartResolver"> <property name="excludeUrls" value="example"/> <!-- url中帶有example的http請求就不會被multipartResolver先解析--> </bean>
通過上面的辦法就可以解決MultipartResolver 和ServletFileUpload 衝突的問題了。