在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 冲突的问题了。