33

我正在开发一个 json REST Web 服务,该服务将从使用主干网构建的单个网页应用程序中使用。

此 API 将允许消费者上传与某些实体相关的文件,例如与项目相关的 pdf 报告

谷歌搜索并在堆栈溢出方面进行了一些研究,我提出了这些可能的方法:

第一种方法: base64 编码数据字段

POST: /api/projects/234/reports
{
  author: 'xxxx',
  abstract: 'xxxx',
  filename: 'xxxx',
  filesize: 222,
  content: '<base64 encoded binary data>'
}

第二种方法:多部分表单发布:

POST: /api/projects/234/reports
{
  author: 'xxxx',
  abstract: 'xxxx',
}

作为回应,我将获得一个报告 ID,然后我将发布另一个帖子

POST: /api/projects/234/reports/1/content
enctype=multipart/form-data

然后只发送二进制数据

(看看这个:https ://stackoverflow.com/a/3938816/47633 )

第三种方法:将二进制数据发布到单独的资源并保存 href

首先我在客户端生成一个随机密钥并在那里发布二进制内容

POST: /api/files/E4304205-29B7-48EE-A359-74250E19EFC4
enctype=multipart/form-data

接着

POST: /api/projects/234/reports
{
  author: 'xxxx',
  abstract: 'xxxx',
  filename: 'xxxx',
  filesize: 222,
  href: '/api/files/E4304205-29B7-48EE-A359-74250E19EFC4'
}

(见:https ://stackoverflow.com/a/4032079/47633 )

我只是想知道是否有任何其他方法可以使用,每种方法的优缺点,以及是否有任何既定的方法来处理这种要求

我看到第一种方法的最大缺点是我必须在客户端上完全加载和 base64 编码文件

一些有用的资源:

4

3 回答 3

18

我的研究结果:

  1. 单个请求(包括数据)

    该请求包含元数据。数据是元数据的属性并经过编码(例如:Base64)。

    优点:

    • 事务性的
    • 每次都有效(不丢失元数据或数据)

    缺点:

    • 编码使请求非常大

    例子:

  2. 单个请求(多部分)

    该请求包含一个或多个带有元数据和数据的部分。

    内容类型:

    优点:

    • 事务性的
    • 每次都有效(不丢失元数据或数据)

    缺点:

    例子:

    • Confluence(包含数据和元数据部分)
    • Jira(一部分用于数据,仅元数据部分用于文件名和 MIME 类型的标题)
    • Bitbucket(一部分用于数据,没有元数据)
    • Google Drive(一部分用于元数据,一部分用于数据)
  3. 单个请求(HTTP 标头和 URL 中的元数据)

    请求正文包含数据和 HTTP 标头,URL 包含元数据。

    优点:

    • 事务性的
    • 每次都有效(不丢失元数据或数据)

    缺点:

    • 没有嵌套的元数据

    例子:

  4. 两个请求

    一个元数据请求和一个或多个数据请求。

    优点:

    • 可扩展性(例如:数据请求可以到存储库服务器)
    • 可恢复(参见例如Google Drive

    缺点:

    • 不是事务性的
    • 并非每次都有效(在第二次请求之前,缺少一部分)

    例子:

于 2016-06-02T11:23:38.460 回答
8

我想不出任何其他方法。

在您的 3 种方法中,我最常使用方法 3。我看到的最大区别是第一种方法和其他两种方法:将元数据和内容分成 2 个资源

  • 优点:可扩展性
    • 虽然您的解决方案涉及发布到同一服务器,但可以轻松更改为将内容上传指向单独的服务器(即 Amazon S3)
    • 在第一种方法中,为用户提供元数据的同一台服务器将有一个进程被大型上传阻塞。
  • 缺点:孤立数据/增加复杂性
    • 失败的上传(元数据或内容)将在服务器数据库中留下孤立的数据
    • 可以使用计划作业清理孤立数据,但这会增加代码复杂性
    • 方法 II 减少了孤立的可能性,代价是更长的客户端等待时间,因为您阻塞了第一个 POST 的响应

第一种方法似乎是最直接的编码方法。但是,如果预计不经常使用此服务,我只会使用第一种方法,并且您可以对用户文件上传设置合理的限制。

于 2013-02-23T05:12:43.397 回答
5

我相信最终的方法是 3 号(单独的资源),因为它允许最大化我从 HTTP 标准中获得的价值,这与我对 REST API 的看法相符。例如,假设正在使用一个基础良好的 HTTP 客户端,您将获得以下好处:

  • 内容压缩:如果客户端表示支持,您的 API 不变,现有客户端继续工作,未来的客户端可以使用它,您可以通过允许服务器以压缩结果响应来进行优化
  • 缓存:If-Modified-Since、ETag 等。客户端可以避免完全重新获取二进制数据
  • 内容类型抽象:例如,您需要上传的图像,它可以是类型image/jpegimage/png. HTTP 标头AcceptContent-type为我们提供了一些优雅的语义,用于在客户端和服务器之间进行协商,而无需将其全部硬编码为我们的架构和/或 API 的一部分

另一方面,如果所讨论的二进制数据不是可选的,我相信可以得出这样的结论:这种方法不是最简单的。在这种情况下, Eric Hu 的答案中列出的缺点将发挥作用。

于 2014-09-05T09:50:45.717 回答