2013-02-25 15 views
23

Tôi có một @Controller bảo vệ với Xuân An và OAuth2 trong đó tôi đang cố gắng để cho người dùng của tôi tải lên một tập tin:Xuân An & Multipart yêu cầu

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

Khi tôi cố gắng để tải lên một tập tin và tiêu đề, tôi nhận ngoại lệ sau. Tôi đang đặt tiêu đề Loại nội dung thành nhiều phần/biểu mẫu dữ liệu.

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) 

Tôi làm cách nào để tải tệp lên phía sau Spring Security? Nó có vẻ như yêu cầu không bao giờ được biến thành một MultiPartHttpServerRequest và do đó, nó không hoạt động?

Nếu tôi thay đổi chữ ký phương pháp của tôi để có một @RequestParam MultipartFile, sau đó tôi nhận được một ngoại lệ như:

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) 

... nhưng tôi có một MultipartResolver cấu hình trong XML của tôi:

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

Tôi đã xem this blog post about getting this working under Spring 3.0 - nhưng tôi đang cố gắng cập nhật hơn và đang sử dụng 3.1 hiện tại. Có lẽ có sửa chữa cập nhật không?

Trả lời

24

Vấn đề là tôi đang sử dụng PUT thay vì POST. Commons FileUpload được mã hóa cứng để chỉ chấp nhận các yêu cầu POST cho các tệp.

Kiểm tra isMultipartContent method tại đó. Để khắc phục điều này, hãy sử dụng POST hoặc mở rộng lớp đó và ghi đè phương thức đó để làm việc theo cách bạn muốn.

Tôi đã mở FILEUPLOAD-214 cho sự cố này.

+4

FILEUPLOAD-214 đã được giải quyết bằng WONTFIX. Theo các tác giả 'PUT' không nên được sử dụng với' Multipart' – beerbajay

+1

Có, và cuối cùng tôi đã thay đổi thành POST thay vì PUT. –

+0

Nó đã được sửa trong phiên bản 1.3 – thomaux

-1

bạn có thể xem https://github.com/joshlong/the-spring-tutorial có ví dụ minh họa cách đăng lên Spring MVC với Spring Security OAuth được bật. Tôi thậm chí sử dụng kéo và thả HTML5 để kéo hình ảnh lên màn hình rồi gửi nó qua ajax đến máy chủ.

3

Để giải quyết sự cố, không sử dụng Spring MultiPartHttpServerRequest, thay vì nhận yêu cầu dưới dạng HttpServletRequest, sử dụng thư viện tải tệp apache commons để phân tích cú pháp yêu cầu từ phương thức PUT và xử lý tệp. Dưới đây là một số mẫu mã:

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

Trong Config.groovy

Hãy chắc chắn rằng nhiều phần dữ liệu được kích hoạt,

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

Trong điều khiển thêm bài viết Phương pháp

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'} 

với những, tôi đã có thể tải lên tệp, không có liên quan gì đến Spring Security.