2014-12-11 13 views
8

Tôi hiện đang cố viết phương thức ReST chấp nhận tải lên tệp. Khi người dùng gửi tệp, tôi cũng muốn họ thêm mô tả và một số dữ liệu meta khác liên quan đến nội dung của tệp (ví dụ: "loại" được liên kết với nội dung của tệp). Tôi đang sử dụng MVC Controller mùa xuân sử dụng Spring 4.Tôi có thể trộn các loại phương tiện trong phương thức Spring Rest không?

Đây là một ví dụ về những gì tôi muốn làm:

@RequestMapping(value = "/file", method = RequestMethod.POST) 
public @ResponseBody 
ResponseEntity<MyFileDTO> uploadCustomAnnotationFile(
     @RequestParam("file") MultipartFile uploadFile, 
     @RequestBody MyFileDetailsDTO fileDetails) { 
    log.debug("This is working!"); 
} 

Tuy nhiên, nếu tôi cố gắng để gọi phương pháp này qua Swagger UI, tôi nhận được một ngoại lệ loại phương tiện không được hỗ trợ:

org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'multipart/form-data;boundary=----WebKitFormBoundarycAbgNBTQ09GQTBif' not supported 

Tôi nghi ngờ rằng tôi không thể trộn ứng dụng/json và dữ liệu đa dạng/biểu mẫu trong 1 yêu cầu?

CẬP NHẬT: Dựa trên phản hồi của zeroflagL và theo liên kết được cung cấp đến tài liệu cụ thể cho những gì tôi đang cố gắng thực hiện và sử dụng @RequestPart thay vì @RequestBody, tôi đã thực hiện một lượng nhỏ tiến bộ, nhưng điều này vẫn không hoạt động.

mới phương pháp chữ ký:

@RequestMapping(value = "/file", method = RequestMethod.POST) 
public @ResponseBody 
ResponseEntity<MyFileDTO> uploadCustomAnnotationFile(
     @RequestPart MultipartFile uploadFile, 
     @RequestPart MyFileDetailsDTO fileDetails) { 
    log.debug("This is working!"); 
} 

mới ngoại lệ:

2014-12-11 09:21:45.237 [http-nio-8443-exec-8] ERROR c.i.h.c.ControllerExceptionHandler [ControllerExceptionHandler.groovy:58] - Controller Exception 
org.springframework.web.multipart.support.MissingServletRequestPartException: Required request part 'fileDetails' is not present. 

Cảm ơn trước, Tonya

+1

Lưu ý rằng 'HttpMediaTypeNotSupportedException' cũng có thể được ném nếu lớp @Controller của bạn khai báo định dạng điểm cuối sai trong thuộc tính' consumes' của '@ RequestMapping', ví dụ nếu bạn khai báo' consumes = {"application/json"} 'ở cấp lớp, nhưng sau đó có điểm cuối cần sử dụng" multipart/form-data ". – lanoxx

Trả lời

1

Các Spring documentation rõ ràng giải thích những việc cần làm.

Ý tưởng về ứng dụng trộn/json và nhiều phần/biểu mẫu dữ liệu là sai, vì application/json sẽ là một phần của yêu cầu nhiều phần (sic!).

WebKitFormBoundary dẫn tôi nghĩ rằng bạn cố gửi yêu cầu AJAX từ trình duyệt của mình và tôi tự hỏi bạn có thực sự gửi JSON hay không. AFAIK không thể thêm một phần JSON (thực) một cách rõ ràng như được hiển thị trong tài liệu Spring. Có thể bạn có thể cho chúng tôi thấy mã khách hàng.

Dù sao bạn không thể sử dụng @RequestBody, vì điều đó sẽ bao gồm các tệp bạn muốn tải lên. Bạn sẽ phải sử dụng @RequestPart. Nếu bạn gửi dữ liệu biểu mẫu - thay vì JSON - cùng với các tệp thì bạn không cần bất kỳ chú thích nào cả.

+0

Chưa có mã khách hàng. Như tôi đã nói trong bài viết gốc, tôi đang sử dụng Swagger UI để kiểm tra điểm cuối ReST của tôi. Tôi đã sử dụng chú thích Swing trong một thời gian và '@ RequestBody' là cách tôi định cấu hình các điểm cuối ReST của mình để chấp nhận/mong đợi dữ liệu JSON trong" nội dung "của yêu cầu. Ngay cả khi nó được kết hợp với tham số truy vấn và/hoặc tham số đường dẫn, tôi chưa bao giờ gặp sự cố khi sử dụng '@ RequestBody' trước đây. Tuy nhiên, kết hợp với một MultipartFile ... nó bây giờ là một vấn đề. Phương thức này không mong đợi dữ liệu JSON cho tham số đó và ném ngoại lệ cho loại phương tiện không hợp lệ. –

+0

@TonyaOhrel Swagger UI chạy trong trình duyệt, vì vậy nếu ứng dụng khách cuối cùng của bạn không chạy trong trình duyệt, nó sẽ tạo sự khác biệt. Bạn cũng không cần bất kỳ chú thích nào trong trường hợp này. – zeroflagL

3

Bạn có thể kết hợp các loại phương tiện trong phương pháp Spring REST. @ zeroflagL/câu trả lời có thể đúng. nhưng @RequestPart hoạt động tốt. Đây là mã của tôi, không có gì khác với mã của bạn

@RequestMapping(value = "/interface/member/v1/register.do", method = RequestMethod.POST) 
@ResponseBody 
public RegisterResponse register(@RequestPart(value = "registerRequest") RegisterRequest registerRequest, 
@RequestPart(value = "attachment", required = false) MultipartFile file) throws ServiceException { 
    return memberV1Service.register(registerRequest, file); 
} 

Tôi khuyên bạn nên kiểm tra yêu cầu của mình. không phải mã phía máy chủ của bạn. Đây là mã xem trước thử nghiệm của tôi (Tôi đã thử nghiệm trong Chrome sử dụng Postman)

POST /was/interface/member/v1/register.do HTTP/1.1 
    Host: localhost:8080 
    Cache-Control: no-cache 

    ----WebKitFormBoundaryE19zNvXGzXaLvS5C 
    Content-Disposition: form-data; name="registerRequest" 

    { -- some of my json format content} 
    ----WebKitFormBoundaryE19zNvXGzXaLvS5C 
    Content-Disposition: form-data; name="attachment"; filename="IMG_0089.JPG" 
    Content-Type: image/jpeg 


    ----WebKitFormBoundaryE19zNvXGzXaLvS5C 

Content-Type là mất tích trong thử nghiệm request.This thất bại với MissingServletRequestPartException nguyên nhân yêu cầu bắt buộc phần 'registerRequest' không có mặt.

Bạn có thể thử nghiệm với RESTClient hoặc một cái gì đó khác và kiểm tra Loại nội dung có hiện diện hay không.

Các vấn đề liên quan