2013-02-25 5 views
23

У меня есть @Controller защищенного с Spring Security и OAuth2, в котором я пытаюсь, чтобы мои пользователи загружают файл:Spring Security & Multipart просит

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

При попытке загрузить файл и название, I получить следующее исключение. Я устанавливаю заголовок Content-Type для 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) 

Как я могу загружать файлы за 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) 

... но у меня есть MultipartResolver настроены на мой XML:

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

Я видел this blog post about getting this working under Spring 3.0 - но я стараюсь оставаться более современным и сейчас использую 3.1. Возможно, обновленное исправление?

ответ

24

Проблема в том, что я использую PUT вместо POST. Commons FileUpload жестко закодирован, чтобы принимать только POST-запросы для файлов.

Проверьте isMultipartContent method. Чтобы исправить это, используйте POST или расширьте этот класс и переопределите этот метод для работы, как вам нравится.

Я открыл FILEUPLOAD-214 по этому вопросу.

+4

FILEUPLOAD-214 был разрешен WONTFIX. По словам авторов 'PUT' не следует использовать с' Multipart' – beerbajay

+1

Да, и в конце концов я действительно изменил POST, а не PUT. –

+0

Это исправлено в версии 1.3 – thomaux

-1

вы можете взглянуть на https://github.com/joshlong/the-spring-tutorial, в котором есть пример, демонстрирующий, как отправить сообщение Spring MVC с функцией Spring Security OAuth. Я даже использую перетаскивание HTML5, чтобы перетащить изображение на экран, а затем отправить его через ajax на сервер.

3

Чтобы решить эту проблему, не используйте Spring MultiPartHttpServerRequest, вместо этого, используя запрос как HttpServletRequest, используя библиотеку загрузки файлов apache, чтобы проанализировать запрос из метода PUT и обработать файл. Вот некоторые примеры кода:

ServletFileUpload fileUpload = new ServletFileUpload(new DiskFileItemFactory()); 
List<FileItem> fileItems = fileUpload.parseRequest(httpServletRequest); 
InputStream in = fileItems.get(0).getInputStream(); 
... 
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.

Смежные вопросы