2013-02-25 15 views
23

Mam @Controller zabezpieczony wiosennym Bezpieczeństwa i OAuth2 w którym próbuję niech moi użytkownicy przesłać plik:Wiosna Bezpieczeństwo i Multipart żąda

@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()); 
    } 
} 

Kiedy próbuję załadować plik i tytuł, I uzyskać następujący wyjątek. Ustawiam nagłówek Content-Type na multipart/form-data.

java.lang.IllegalStateException: Current request is not of type [org.springframework.web.multipart.MultipartHttpServletRequest]: SecurityContextHolderAwareRequestWrapper[ FirewalledRequest[ [email protected]]] 
    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) 

Jak mogę przesłać pliki za Spring Security? Wygląda na to, że żądanie nigdy nie zostaje przekształcone w MultiPartHttpServerRequest, więc nie działa?

Jeśli mogę zmienić metodę podpis wziąć @RequestParam MultipartFile, potem uzyskać wyjątek jak:

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) 

... ale ja mam MultipartResolver skonfigurowany w moim XML:

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

Widziałem this blog post about getting this working under Spring 3.0 - ale staram się być bardziej aktualny i obecnie używam wersji 3.1. Czy jest prawdopodobnie zaktualizowana poprawka?

Odpowiedz

24

Problem polega na tym, że używam PUT zamiast POST. Commons FileUpload jest zakodowany na twardo, aby akceptować tylko żądania POST dla plików.

Sprawdź tam isMultipartContent method. Aby to naprawić, użyj POST lub rozszerz tę klasę i zastąp tę metodę, aby działała tak, jak lubisz.

Otworzyłem FILEUPLOAD-214 dla tego problemu.

+4

FILEUPLOAD-214 został rozwiązany przez WONTFIX. Według autorów "PUT" nie powinno być używane z 'Multipart'em – beerbajay

+1

Tak, i ostatecznie zmieniłem się na POST, a nie na PUT. –

+0

Zostało to naprawione w wersji 1.3 – thomaux

-1

możesz rzucić okiem na https://github.com/joshlong/the-spring-tutorial, który ma przykład demonstrujący sposób publikowania w Spring MVC z włączoną aktywacją OAuth Spring Security. Używam nawet przeciągnięcia i upuszczenia HTML5, aby przeciągnąć obraz na ekran, a następnie przesłać go przez serwer ajax.

3

Aby rozwiązać problem, nie używaj sprężyny MultiPartHttpServerRequest, zamiast odbierania żądania jako HttpServletRequest, przy użyciu biblioteki filebug apache commons, aby przeanalizować żądanie z metody PUT i przetworzyć plik. Oto niektóre przykładowy kod:

ServletFileUpload fileUpload = new ServletFileUpload(new DiskFileItemFactory()); 
List<FileItem> fileItems = fileUpload.parseRequest(httpServletRequest); 
InputStream in = fileItems.get(0).getInputStream(); 
... 
2

W Config.groovy

Upewnij wieloczęściowy jest włączona,

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

kontroler dodać metody 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'} 

z nich, ja był w stanie przesłać plik, nic związanego z Spring Security.

Powiązane problemy