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に変換されないように見えるので、動作しませんか?
メソッドシグネチャを変更して@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を使用しています。おそらく更新された修正はありますか?
問題は、POSTではなくPUTを使用していることです。 Commons FileUploadは、ファイルのPOST要求のみを受け入れるようにハードコードされています。
isMultipartContentメソッド を確認してください。これを修正するには、POSTを使用するか、そのクラスを拡張し、そのメソッドをオーバーライドして好きなように動作させます。
この問題のために FILEUPLOAD-214 を開きました。
この問題を解決するには、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();
...
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に関連するものは何もありませんでした。