Spring MultipartResolver 或者 ServletFileUpload 冲突导致获取不到http数据/Multipart数据为空

如果不知道MultipartResolver 或者ServletFileUpload 的,请 JAVA Server上传文件 Spring MultipartResolver 或者 ServletFileUpload

如果同时使用了MultipartResolver和ServletFileUpload,就会在iter.hasNext()返回false.然后整个循环就跳出去了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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"));
}
}
}
}

整个问题产生的原因是Spring框架先调用了MultipartResolver 来处理http multi-part的请求。这里http multipart的请求已经消耗掉。后面又交给ServletFileUpload ,那么ServletFileUpload 就获取不到相应的multi-part请求。

如果帐前 卒想快速解决这个问题。解决方法是加入帐前卒的 multipartResolver, 来单独处理某些请求。这些请求需要特判。例如下面的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
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);
}

}

然后在web.xml中这样写:

1
2
3
4
<bean id="multipartResolver" class="example.MyMultipartResolver">
<property name="excludeUrls" value="example"/>
<!-- url中带有example的http请求就不会被multipartResolver先解析-->
</bean>