我有一个正常工作的文件上传表单,除非我发送的文件大于我在 Spring 中配置的大小。
我之前在另一个用 Spring 编写的应用程序上使用过相同的代码,不同之处在于我使用的是 ExtJs 4.2,现在使用的是 ExtJs 6.0。旧应用程序使用 Spring security 3,新应用程序使用 4。
Spring 端已配置为阻止超过 3MB 的文件。
从 WebMvcConfig.java:
@Bean(name="multipartResolver")
public CommonsMultipartResolver commonsMultipartResolver()
{
ToolkitCommonsMultipartResolver resolver = new ToolkitCommonsMultipartResolver();
resolver.setMaxUploadSize(Constants.UPLOAD_MAX_FILE_SIZE);
return resolver;
}
来自 ToolkitCommonsMultipartResolver:
public class ToolkitCommonsMultipartResolver extends CommonsMultipartResolver {
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
protected MultipartParsingResult parseRequest(final HttpServletRequest request) {
String encoding = determineEncoding(request);
FileUpload fileUpload = prepareFileUpload(encoding);
List fileItems;
try {
fileItems = ((ServletFileUpload) fileUpload).parseRequest(request);
}
catch (FileUploadBase.SizeLimitExceededException ex) {
System.out.println("******* MultipartParsingResult limit exceeded");
request.setAttribute("fileSizeExceeded", ex);
fileItems = Collections.EMPTY_LIST;
}
catch (FileUploadException ex) {
throw new MultipartException("Could not parse multipart servlet request", ex);
}
return parseFileItems(fileItems, encoding);
}
}
我的自定义控制器:
@PreAuthorize("hasAuthority('ACTIVITY_CREATE_UPDATE')")
@RequestMapping(value = "/activity/editActivity", method = RequestMethod.POST, consumes="multipart/form-data", produces=MediaType.TEXT_HTML_VALUE )
public @ResponseBody String editActivity(@Valid ActivityBean bean, BindingResult result, HttpServletRequest request) {
//WebMvcConfig.commonsMultipartResolver will throw exception if file size exceeds the max size
//Passed as a request attribute
Object exception = request.getAttribute("fileSizeExceeded");
if (exception != null && FileUploadBase.SizeLimitExceededException.class.equals(exception.getClass()))
{
log.info("File too large");
String msg = "The file you sent has exceeded the maximum upload size of " + (Constants.UPLOAD_MAX_FILE_SIZE / 1000000L) + " MB.";
return "{\"success\" : false, \"msg\" : \"" + msg + "\"}";
}
...other code to process request
}
}
Spring security http 标记具有以下代码,以允许从服务器显示框架内容(X-Frame-Options)。在我添加此代码之前,所有响应都被阻止(保存成功与否):
<headers>
<frame-options policy="SAMEORIGIN"/>
</headers>
Spring 将返回 success: false 以及我在控制器中设置的消息。在 chrome 中,我看到连接中止(net::ERR_CONNECTION_ABORTED)。在 ExtJs 代码的深处,我找到了 onComplete 方法:
/**
* Callback handler for the upload function. After we've submitted the form via the
* iframe this creates a bogus response object to simulate an XHR and populates its
* responseText from the now-loaded iframe's document body (or a textarea inside the
* body). We then clean up by removing the iframe.
* @private
*/
onComplete: function()
在 onComplete() 里面有上传后的调用
doc = me.getDoc();
此方法尝试访问从 iFrame 中的服务器返回的内容被阻止。在这种情况下,似乎 Spring 安全标头不起作用。有一个抛出错误的捕获(e):
未捕获的 DOMException:阻止具有源“ http://localhost:8080 ”的框架访问跨域框架。(...)
有谁知道如何解决这个问题?我可以禁用 Muitipart 解析器并接受完整的文件,并在我的自定义代码中进行大小验证。如果文件超过大小,首先阻止文件上传更有意义。这是 Spring security 4 还是 ExtJs6 问题?