【问题标题】:REST Service that can consume both JSON and Multipart Form可以使用 JSON 和 Multipart Form 的 REST 服务
【发布时间】:2015-03-19 17:20:36
【问题描述】:

我需要在 Spring MVC 中创建一个可以同时处理 JSON 和 Multipart Form 请求的方法。

这是我的方法的签名:

@RequestMapping(value = { "/upload_image" }, method = RequestMethod.POST)
public @ResponseBody void uploadImage(final ImageDTO image) 

ImageDTO 类如下所示:

public class ImageDTO {
  private String imageUrl;
  private Long imageId;
  private MultipartFile image;

  public String getImageUrl() {
    return imageUrl;
  }

  public void setImageUrl(final String url) {
    this.imageUrl = url;
  }

  public Long getImageId() {
    return imageId;
  }

  public void setImageId(final Long imageId) {
    this.imageId = imageId;
  }

  public MultipartFile getImage() {
    return image;
  }

  public void setImage(MultipartFile image) {
    this.image = image;
  }
}

所以场景是我需要支持两种场景: 1.从form上传图片,Content-Type为multipart-form(所有DTO成员不为null) 2. 使用 JSON 上传图片,仅使用 imageUrl。 在这种情况下,请求正文如下所示:

{
    "imageId":"1236",
    "imageUrl":"http://some.image.url",
    "image":null
}

当前实现可以很好地处理多部分请求,但是在发送 JSON 时,ImageDTO 对象的所有成员中都包含 NULL。

是否可以让同一个方法处理两种内容类型?

谢谢。

【问题讨论】:

    标签: java json rest spring-mvc


    【解决方案1】:

    要接收 JSON,您需要使用 @RequestBody 标记 ImageDTO 参数

    @RequestMapping(value = { "/upload_image" }, method = RequestMethod.POST)
    public @ResponseBody void uploadImage(final @RequestBody ImageDTO image) 
    

    【讨论】:

    • 谢谢。我已经尝试过了,这确实使 JSON 工作,但是在发送 multipart-form 请求时它失败并且错误说 multipart-form 内容类型不受支持。
    • 是的,你不能直接这样做。
    • 我明白了。非常感谢。
    【解决方案2】:

    遇到过类似的情况,这就是我想出的。两者都不是那么干净的方式,但可以完美地工作。您需要从客户端发送多部分请求

    注意:保存文件的变量的数据类型是InputStream。你需要相应地改变它

    1. 这在您不知道您的文件数量的情况下很有用 正在接收您的请求。

      // imports
      import org.apache.commons.fileupload.servlet.ServletFileUpload;
      import org.apache.commons.fileupload.FileItem;
      import org.apache.commons.fileupload.disk.DiskFileItemFactory;
      
      // code flow
      // HttpServletRequest request
      final FileItemFactory factory = new DiskFileItemFactory();
      final ServletFileUpload fileUpload = new ServletFileUpload(factory);
      List items = null;
      private Map<String, InputStream> fileMap = new HashMap<String, InputStream>();
      
      if (ServletFileUpload.isMultipartContent(request)) {
      
          // get the request content and iterate through
          items = fileUpload.parseRequest(request);
      
          if (items != null) {
              final Iterator iter = items.iterator();
              while (iter.hasNext()) {
                  final FileItem item = (FileItem) iter.next();
                  final String fieldName = item.getFieldName();
                  final String fieldValue = item.getString();
                  // this is for non-file fields
                  if (item.isFormField()) {
                      switch (fieldName) {
                          case "imageId" :
                          // set inside your DTO field
                          break;
      
                          // do it for other fields
                      }
      
                  } else {
                     // set the image in DTO field
                  }
              }
          }
      }
      
    2. 在这种情况下,您将不得不处理固定数量的表格 字段。我在 ReST 方法中实现如下:

      @Path("/upload")
      @POST
      @Consumes(MediaType.MULTIPART_FORM_DATA)
      public ResponseDTO upload(FormDataMultiPart multiPartData) {
      
               // non-file fields
               final String imageId = multiPartData.getField("imageId").getValue();
      
               // for file field    
               final FormDataBodyPart imagePart = multiPartData.getField("image");
               final ContentDisposition imageDetails= imagePart.getContentDisposition();
               final InputStream imageDoc = imagePart.getValueAs(InputStream.class);
      
               // set the retrieved content in DTO
      }
      

    【讨论】:

    • 这看起来像 Jax-Rs 而不是 Spring MVC
    • 如果我理解正确,这将要求请求始终使用内容类型“multipart-form”。我想知道是否有可能使该方法既能处理多部分形式,又能处理请求中的json。
    • 是的,这将需要多部分表单请求。您不能在 JSON 请求中发送文件内容。
    【解决方案3】:

    在我引入 @ModelAttribute 注释之前,我得到了相同的结果 - 所有 DTO 成员中的 NULL。现在一切正常,这是工作代码:

    控制器方法

    @RequestMapping(value = "/save", method = RequestMethod.POST,
            consumes = { "multipart/form-data" })
    public void create(@Valid @ModelAttribute("entryForm") final EntryDTO entryDTO,
            final BindingResult validationResult) throws FormValidationError {
        validate(entryDTO, validationResult);
        entryService.save(entryDTO);
    }
    

    DTO

    public class EntryDTO {
    
        private String phrase;
    
        private String translation;
    
        private MultipartFile imageFile;
    
    }
    

    表格

    <form method="post" name="entryForm" action="http://localhost:8080/save"
            enctype="multipart/form-data">
        <p><input type="text" name="phrase" value="test"/> phrase</p>
        <p><input type="text" name="translation" value="тест"/> translation</p>
        <p><input type="file" name="imageFile"/></p>
        <p><input type="submit"/></p>
    </form>
    

    注意,表单名为“entryForm”,对应的@ModelAttribute(“entryForm”)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-08
      • 1970-01-01
      • 1970-01-01
      • 2016-07-03
      • 2020-07-24
      • 1970-01-01
      相关资源
      最近更新 更多