我正在尝试使用spring 3上传一个带有一个参数的文件。
这是我应该启用此服务的控制器方法:
@RequestMapping(value="/{id}", method = RequestMethod.PUT, headers="content-type=multipart/form-data")
public ResponseEntity<String> uploadImageWithJsonParamater(@PathVariable("id") Long id, @RequestParam String json, @RequestParam MultipartFile customerSignFile) {
//...
}
问题是,服务器无法调度到此方法: MissingServletRequestParameterException:必需的String参数'json'不存在
如果我将RequestMethod从PUT更改为POST,一切都很好。那么有人知道这个问题吗?
似乎不允许通过PUT传输表单数据。
我调试了一下,以下方法在PUT情况下返回false但在POST情况下为true:
public boolean isMultipart(HttpServletRequest request) {
return (request != null && ServletFileUpload.isMultipartContent(request));
}
我将不胜感激任何帮助!
提前致谢!
答案 0 :(得分:5)
您可以使用spring HiddenHttpMethodFilter来完成此操作,但是您需要确保在Web.xml过滤器链中的HiddenHttpMethodFilter之前放置一个Spring MultipartFilter。
例如:在您的web.xml中
<filter>
<filter-name>MultipartFilter</filter-name>
<filter-class>org.springframework.web.multipart.support.MultipartFilter</filter-class>
<init-param>
<param-name>multipartResolverBeanName</param-name>
<param-value>filterMultipartResolver</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>MultipartFilter</filter-name>
<servlet-name>/*</servlet-name>
</filter-mapping>
<filter>
<filter-name>HiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HiddenHttpMethodFilter</filter-name>
<servlet-name>/*</servlet-name>
</filter-mapping>
然后在spring-config.xml中添加对CommonsMultipartResolver的引用:
<bean id="filterMultipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>
请注意,如果您不添加spring-config.xml条目,则MultipartFilter将默认使用使用servlet规范3.0实现的MultipartResolver,并将抛出如下错误: NoSuchMethodError HttpServletRequest.getParts()如果你没有使用3.0。
答案 1 :(得分:4)
我遇到了同样的问题。
我的解决方案是实现ExtendedMultipartResolver
,它接受通过http方法PUT发送的多部分。
只需复制CommonsMultipartResolver
代码,重命名该类并根据需要更改isMultipart()
函数的实现:
private boolean isMultipartContent(HttpServletRequest request) {
String httpMethod = request.getMethod().toLowerCase();
// test for allowed methods here...
String contentType = request.getContentType();
return (contentType != null && contentType.toLowerCase().startsWith("multipart"));
}
public boolean isMultipart(HttpServletRequest request) {
return (request != null && isMultipartContent(request));
}
您可以在此处检查POST,PUT或其他HTTP方法。就我而言,所有方法都会被接受, 因为我的控制器注释将过滤到允许的方法。
不要忘记在spring web上下文中配置bean:
<bean id="multipartResolver" class="sample.package.ExtendedMultipartResolver"/>
希望有所帮助。
欢呼声 克里斯
答案 2 :(得分:2)
您无法根据HTML标准通过PUT发送表单数据。你只能通过PUT发送文件,在这种情况下,它们发送效率更高,然后使用POST(因为你不再拥有所有的多部分开销),但是为了让你PUT监听服务器端组件实际接收文件通过PUT你必须确保你实际发送一个PUT命令(例如通过javascript)。这是一个使用JQuery的例子:
$('#file_upload').fileUpload({
namespace: 'file_upload',
url: '/path',
method: 'PUT'
});
答案 3 :(得分:1)
我实施了一个略有不同的解决方案,灵感来自http://rugal.ga/development/2015/10/03/uploading-file-other-than-post/,并接近上一篇文章:
public class ExtendedMultipartResolver extends CommonsMultipartResolver {
@Override
public boolean isMultipart(HttpServletRequest request) {
return (request != null && isMultipartContent(request));
}
/**
* Extends ServletFileUpload.isMultipartContent() behavior to allow PUT requests as multipart.
*
* @param request
* The servlet request to be evaluated. Must be non-null.
*
* @return <code>true</code> if the request is multipart; <code>false</code> otherwise.
* @see org.apache.commons.fileupload.servlet.ServletFileUpload#isMultipartContent
*/
public static final boolean isMultipartContent(HttpServletRequest request) {
HttpMethod httpMethod = HttpMethod.valueOf(request.getMethod());
if (HttpMethod.POST != httpMethod && HttpMethod.PUT != httpMethod) {
return false;
}
return FileUploadBase.isMultipartContent(new ServletRequestContext(request));
}
}
这里没什么新东西,除了我的代码依赖于org.apache.commons.fileupload.FileUploadBase.isMultipartContent(RequestContext)而不是复制其内容。
现在,如果你需要实现文件上传服务的单元测试,你可能会以下列方式使用org.springframework.test.web.servlet.request.MockMvcRequestBuilders.fileUpload():
@Test
public void testUploadFilePost() throws Exception {
MockMultipartFile multipartFile = new MockMultipartFile(...);
String url = ...;
mockMvc.perform(fileUpload(url).file(multipartFile)).andExpect(status().isOk());
}
上面的代码只能发出POST请求,因为org.springframework.test.web.servlet.request.MockMultipartHttpServletRequestBuilder的实现方式。为了对PUT文件上传进行单元测试,您可能会对以下代码感兴趣:
private static final RequestPostProcessor PUT_REQUEST_POST_PROCESSOR = new RequestPostProcessor() {
@Override
public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) {
request.setMethod(HttpMethod.PUT.name());
return request;
}
};
private static MockHttpServletRequestBuilder putFileUpload(String url, MockMultipartFile multipartFile,
Object... urlVariables) {
return fileUpload(url, urlVariables).file(multipartFile).with(PUT_REQUEST_POST_PROCESSOR);
}
现在可以通过以下方式调整测试:
@Test
public void testUploadFilePut() throws Exception {
MockMultipartFile multipartFile = new MockMultipartFile(...);
String url = ...;
mockMvc.perform(putFileUpload(url, multipartFile)).andExpect(status().isOk());
}