协慌网

登录 贡献 社区

最好以 JSON 形式将文件和关联数据发布到 RESTful WebService

这可能是一个愚蠢的问题,但我有一个夜晚。在一个应用程序中,我正在开发 RESTful API,我们希望客户端将数据作为 JSON 发送。此应用程序的一部分要求客户端上载文件(通常是图像)以及有关该图像的信息。

我很难追踪单个请求中的情况。是否可以将文件数据 Base64 转换为 JSON 字符串?我需要在服务器上执行 2 个帖子吗?我不应该为此使用 JSON 吗?

附带说明一下,我们在后端使用 Grails,并且本机移动客户端(iPhone,Android 等)可以访问这些服务(如果有区别的话)。

答案

我在这里问了类似的问题:

如何使用 REST Web 服务上载带有元数据的文件?

您基本上有三个选择:

  1. Base64 对文件进行编码,但代价是将数据大小增加了约 33%,并在服务器和客户端中增加了用于编码 / 解码的处理开销。
  2. 首先在multipart/form-data POST 中发送文件,然后将 ID 返回给客户端。然后,客户端发送带有 ID 的元数据,然后服务器将文件和元数据重新关联。
  3. 首先发送元数据,然后将 ID 返回给客户端。然后,客户端发送带有 ID 的文件,然后服务器将文件和元数据重新关联。

您可以使用 multipart / form-data内容类型在一个请求中发送文件和数据:

在许多应用中,有可能向用户呈现表格。用户将填写该表单,包括键入的信息,通过用户输入生成的信息或包含在用户选择的文件中的信息。填写表单后,表单中的数据将从用户发送到接收应用程序。

MultiPart / Form-Data 的定义源自这些应用程序之一。

http://www.faqs.org/rfcs/rfc2388.html

“multipart / form-data” 包含一系列部分。每个部分均应包含一个内容处理标头 [RFC 2183],其中处理类型为 “form-data”,并且该处理包含一个(附加)参数 “name”,其中该参数的值为原始值。表单中的字段名称。例如,零件可能包含标题:

内容处置:表单数据;名称 =“用户”

其值与 “用户” 字段的输入相对应。

您可以在边界之间的每个部分中包括文件信息或字段信息。我已经成功实现了 RESTful 服务,该服务要求用户提交数据和表单,并且 multipart / form-data 可以完美地工作。该服务是使用 Java / Spring 构建的,而客户端使用的是 C#,因此,不幸的是,我没有任何 Grails 示例可以为您提供有关如何设置服务的信息。在这种情况下,您不需要使用 JSON,因为每个 “表单数据” 部分都为您提供了一个位置,用于指定参数的名称及其值。

使用 multipart / form-data 的好处是,您使用的是 HTTP 定义的标头,因此您坚持使用现有 HTTP 工具创建服务的 REST 理念。

我知道这个线程已经很老了,但是,我这里缺少一个选项。如果您拥有要发送的元数据(任何格式)以及要上传的数据,则可以提出一个multipart/related请求。

Multipart / Related 媒体类型适用于由几个相互关联的身体部位组成的复合对象。

您可以查看RFC 2387规范以了解更多详细信息。

基本上,此类请求的每个部分都可以具有不同类型的内容,并且所有部分都以某种方式相关(例如,图像及其元数据)。零件由边界字符串标识,最后的边界字符串后跟两个连字符。

例子:

POST /upload HTTP/1.1
Host: www.hostname.com
Content-Type: multipart/related; boundary=xyz
Content-Length: [actual-content-length]

--xyz
Content-Type: application/json; charset=UTF-8

{
    "name": "Sample image",
    "desc": "...",
    ...
}

--xyz
Content-Type: image/jpeg

[image data]
[image data]
[image data]
...
--foo_bar_baz--