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の背後でファイルをアップロードするにはどうすればよいですか?リクエストがMultiPartHttpServerRequestに変換されないようで、機能しませんか?

メソッドシグネチャを変更して@RequestParamMultipartFileを取得すると、次のような例外が発生します。

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

問題は、POSTの代わりにPUTを使用していることです。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'}

これらを使用して、ファイルをアップロードできました。SpringSecurityに関連するものは何もありません。

于 2014-07-21T18:53:09.460 に答える
-1

https://github.com/joshlong/the-spring-tutorialをご覧ください。この例には、SpringSecurityOAuthを有効にしてSpringMVCに投稿する方法を示す例があります。HTML5のドラッグアンドドロップを使用して画像を画面にドラッグし、ajax経由でサーバーに送信します。

于 2013-02-26T19:46:53.927 に答える