@FormDataParam和@FormParam有什么区别?

24
“@FormDataParam”和“@FormParam”的区别是什么?
我在一个方法中使用了多个“@FormDataParam”但出现了“不支持的媒体类型”错误。但当我使用“@FormParam”时,我得到了值。
因此,我需要知道它们两者之间的区别是什么?

FormDataParam与multipart/form-data一起使用。这是传输二进制数据(如附件)比使用FormParam更有效的方法。请参阅FormDataParam文档 - Sangram Jadhav
2个回答

33
  • @FormDataParam 应该与多部分类型数据一起使用(即 multipart/form-dataMediaType.MULTIPART_FORM_DATA),它的原始形式看起来像:

      Content-Type: multipart/form-data; boundary=AaB03x
    
      --AaB03x
      Content-Disposition: form-data; name="submit-name"
    
      Larry
      --AaB03x
      Content-Disposition: form-data; name="files"; filename="file1.txt"
      Content-Type: text/plain
    
      ... contents of file1.txt ...
      --AaB03x--
    

    Multipart 主要用于发送二进制数据,例如非文本文件,或者在发送文件时附带任意、元数据或相关数据。

  • @FormParam 用于处理 URL 编码的请求参数(即 application/x-www-form-urlencodedMediaType.APPLICATION_FORM_URLENCODED),其原始形式如下:

      param1=value1&param2=value2
    

这两种类型主要用于客户端表单。例如:

<form method="POST" action="someUrl">
    <input name="gender" type="text">
    <input name="name" type="text">
</form>

上述操作会将请求参数发送为application/x-www-form-urlencoded格式。它将以原始形式发送。

gender=male&name=peeskillet

在服务器端,我们可以为表单中的每个命名参数使用@FormParam

@FormParam("gender") String gender, @FormParam("name") String name

但是,如果我们需要在参数中发送图像等内容,application/x-form-url-encoded 数据类型是不够的,因为它只处理文本。所以我们需要使用多部分数据(Multipart)。

<form method="POST" action="someUrl", enctype="multipart/form-data">
    <input name="gender" type="text">
    <input name="name" type="text">
    <input name="avatar" type="file">
</form>

这里指定了多部分类型,现在浏览器将使用类似以下内容的请求发送出去:

Content-Type: multipart/form-data; boundary=AaB03x

--AaB03x
Content-Disposition: form-data; name="gender"

Male
--AaB03x
Content-Disposition: form-data; name="name"

Peskillet
--AaB03x
Content-Disposition: form-data; name="avatar"; filename="image.png"
Content-Type: image/png

... binary content of image file ...
--AaB03x--

在服务器上,与上面的 application/x-www-form-urlencoded 示例类似,对于每个Multipart参数(或更准确地说是字段),我们可以使用@FormDataParam 来表示每个参数。

@FormDataParam("gender") String gender,
@FormDataParam("name") String name,
@FormDataParam("avatar") InputStream avatar

参见:


1
是的,现在很清楚了。但唯一我没有理解的是我的表单未使用multipart/form-data。尽管如此,当我只有一个参数时,我仍然能够将字符串作为@FormDataParam获取。但当我更改为两个参数后它就停止工作了。将其更改为@FormParam后,现在它可以工作了。 - Partha Sarathi Ghosh
1
我认为在你的情况下,@FormDataParam 被完全忽略了,因为期望的媒体类型是 application/x-www-form-urlencoded。至于传入的数据,因为没有使用 @FormParam,所以它只会将整个请求字符串作为数据返回给你。 - Paul Samsotha
就“不起作用”而言,这是因为一个方法只能接受一个主体参数,通常此参数没有注释,例如获取JSON POJO时。如果您尝试添加一个以上的参数,则Jersey不知道哪个是主体参数,因此会在启动时抛出错误。如果您向应用程序注册了MultiPartFeature,则Jersey不会抛出错误,因为该功能识别@FormDataParam注释,因此它认为这是您期望的内容。虽然我不确定反序列化是否会成功。 - Paul Samsotha
你可以查看这个相关的帖子 - Paul Samsotha

3

根据FormParam文档:

将请求实体体中包含的表单参数的值绑定到资源方法参数上。除非使用Encoded注释禁用,否则对值进行URL解码。可以使用DefaultValue注释指定默认值。如果请求实体体不存在或不支持媒体类型,则使用默认值。

FormDataParam:

将“multipart/form-data”请求实体体的命名主体部分绑定到资源方法参数上。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接