23

我有一个受 Spring Security 和 OAuth2 保护的 @Controller,我试图让我的用户上传文件:

@Controller
@RequestMapping(value = "/api/image")
public class ImageController {

    @PreAuthorize("hasAuthority('ROLE_USER')")
    @RequestMapping(value = "/upload", method = RequestMethod.PUT)
    public @ResponseBody Account putImage(@RequestParam("title") String title, MultipartHttpServletRequest request, Principal principal){
        // Some type of file processing...
        System.out.println("-------------------------------------------");
        System.out.println("Test upload: " + title);
        System.out.println("Test upload: " + request.getFile("file").getOriginalFilename());
        System.out.println("-------------------------------------------");

        return ((Account) ((OAuth2Authentication) principal).getPrincipal());
    }
}

当我尝试上传文件和标题时,出现以下异常。我将 Content-Type 标头设置为 multipart/form-data。

java.lang.IllegalStateException: Current request is not of type [org.springframework.web.multipart.MultipartHttpServletRequest]: SecurityContextHolderAwareRequestWrapper[ FirewalledRequest[ org.apache.catalina.connector.RequestFacade@1aee75b7]]
    at org.springframework.web.servlet.mvc.method.annotation.ServletRequestMethodArgumentResolver.resolveArgument(ServletRequestMethodArgumentResolver.java:84)
    at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:75)
    at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:156)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:117)

如何在 Spring Security 后面进行文件上传?似乎请求永远不会变成 M​​ultiPartHttpServerRequest ,所以它不起作用?

如果我将我的方法签名更改为采用@RequestParam MultipartFile,那么我会收到如下异常:

DEBUG DefaultListableBeanFactory - Returning cached instance of singleton bean 'imageController'
DEBUG ExceptionHandlerExceptionResolver - Resolving exception from handler [public com.tinsel.server.model.Account com.tinsel.server.controller.ImageController.putImage(java.lang.String,org.springframework.web.multipart.MultipartFile,java.security.Principal)]: java.lang.IllegalArgumentException: Expected MultipartHttpServletRequest: is a MultipartResolver configured?
DEBUG ResponseStatusExceptionResolver - Resolving exception from handler [public com.tinsel.server.model.Account com.tinsel.server.controller.ImageController.putImage(java.lang.String,org.springframework.web.multipart.MultipartFile,java.security.Principal)]: java.lang.IllegalArgumentException: Expected MultipartHttpServletRequest: is a MultipartResolver configured?
DEBUG DefaultHandlerExceptionResolver - Resolving exception from handler [public com.tinsel.server.model.Account com.tinsel.server.controller.ImageController.putImage(java.lang.String,org.springframework.web.multipart.MultipartFile,java.security.Principal)]: java.lang.IllegalArgumentException: Expected MultipartHttpServletRequest: is a MultipartResolver configured?
DEBUG DispatcherServlet - Could not complete request
java.lang.IllegalArgumentException: Expected MultipartHttpServletRequest: is a MultipartResolver configured?
    at org.springframework.util.Assert.notNull(Assert.java:112)

...但我确实在我的 XML 中配置了 MultipartResolver:

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <property name="maxUploadSize" value="268435456"/> <!-- 256 megs -->
</bean>

我确实看到了这篇关于在 Spring 3.0 下让它工作的博客文章——但我正在努力保持最新状态,目前正在使用 3.1。是否有更新的修复?

4

4 回答 4

25

问题是我使用的是 PUT 而不是 POST。Commons FileUpload 被硬编码为只接受文件的 POST 请求。

检查那里的isMultipartContent 方法。要解决此问题,请使用 POST 或扩展该类并覆盖该方法以按照您的喜好工作。

我为此问题打开了 FILEUPLOAD-214 。

于 2013-02-25T20:02:01.100 回答
3

为了解决这个问题,不要使用spring MultiPartHttpServerRequest,而是将请求作为HttpServletRequest,使用apache commons fileupload库解析来自PUT方法的请求,并处理文件。以下是一些示例代码:

ServletFileUpload fileUpload = new ServletFileUpload(new DiskFileItemFactory());
List<FileItem> fileItems = fileUpload.parseRequest(httpServletRequest);
InputStream in = fileItems.get(0).getInputStream();
...
于 2013-07-06T19:50:36.917 回答
2

在 Config.groovy

确保启用多部分,

// whether to disable processing of multi part requests
   grails.web.disable.multipart=false

在控制器中添加 Post 方法

def upload(){
    MultipartHttpServletRequest mpr = (MultipartHttpServletRequest)request;
    if(request instanceof MultipartHttpServletRequest)
            {
                CommonsMultipartFile f = (CommonsMultipartFile) mpr.getFile("myFile");
                println f.contentType
                f.transferTo()
                if(!f.empty)
                    flash.message = 'success'
                else
                    flash.message = 'file cannot be empty'
            }
    else
    flash.message = 'request is not of type MultipartHttpServletRequest'}

有了这些,我就可以上传文件了,没有什么与 Spring Security 相关的。

于 2014-07-21T18:53:09.460 回答
-1

您可以查看https://github.com/joshlong/the-spring-tutorial,其中有一个示例演示如何在启用 Spring Security OAuth 的情况下发布到 Spring MVC。我什至使用 HTML5 拖放将图像拖到屏幕上,然后通过 ajax 将其提交到服务器。

于 2013-02-26T19:46:53.927 回答