1

我有一个正常工作的文件上传表单,除非我发送的文件大于我在 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 问题?

4

0 回答 0