16

使用 REST API 交付二进制资源(如 pdf 文件)的约定是什么?您是否只是在 JSON 或 XML 响应中返回资源的 URL,例如 {"url" : "http://example.com/document.pdf"} ?

我试图理解 URI 和 URL 之间的区别并保持 RESTful 哲学。诚然,这对我来说是新的,所以我可能会误解一些事情。

4

3 回答 3

13

本节假设您的意思是:我如何告诉用户在哪里可以找到二进制资源

URI 和 URL 之间的区别与二进制数据类型与非二进制数据类型没有任何关系(另请参见 参考资料)。

如果您返回的主要是 JSON,那么url条目是一种常见的方式。如果您正在做一些更类似于 HTML/XML 的事情,那么像<link>具有良好rel属性的元素之类的事情就很有意义。

显然,如果客户端GET向您提供给他们的直接 URL 发出请求,那么您应该将文件发送给他们,除非他们发送了一堆内容协商标头,从而有效地阻止您完成他们的请求。在这种情况下,406 Not Acceptable响应(或官方定义)很有意义。

如果您的问题是其他意思,请澄清。

漫无边际的“这样做”部分

第一:忽略 URL 与 URI。它与此无关。完全没有。

下一篇:如果您的问题不是“我如何链接到资源”(这可能会受到我将要讨论的内容的影响),而是“如果我的资源只是一个 PDF 文件怎么办”,那么您有各种各样的解决它的选项。首先,你需要退后一步,更抽象地思考(一点点)。您的资源几乎肯定不是“PDF 文件”。它是“用户上传的文件”,或“我生成的 PDF 版本的报告”等。

在第一种情况下,除了他们发送给您的二进制文件之外,您可能没有任何资源表示,这完全没问题。GET当您收到该资源的 URL时,您可能不需要执行任何类型的内容协商。只需将文件发送给他们,但要遵守我上面提到的警告406

在第二种情况下,您可能拥有该资源的各种表示形式:CSV、HTML、LaTeX,应有尽有。在这种情况下,当您收到GET资源的 URL 时,您确实需要进行一些内容协商,以便您知道是否向他们发送 PDF 文档或其他内容。您可能拥有资源的 JSON 表示形式,它只是您用于生成 PDF 的原始数据。

在任何一种情况下,如果您有一个完全是关于资源的元数据的表示,那将是出乎意料的。如果需要(通常是,有时不是),显式的外部元数据(与嵌入在二进制资源中的元数据相反,例如 PDF 中的作者和标题信息)最常被建模为单独的资源。

最后,正如@monitorjbl 所说:您可能不想将二进制数据直接嵌入文本格式,例如 JSON 或 XML。有很多方法可以做到这一点,通常涉及“base64-encoded”这个词,但这通常不是最好的方法。一般来说,您不应该混合二进制数据和文本数据。

于 2012-08-29T20:06:07.593 回答
6

无论是否二进制,您的 REST 资源都应使用超媒体类型进行描述。

  • 如果您的 REST 客户端以 msgpack 格式 PUT/POST 资源,则 REST 服务器仍然可以读取此消息并更新/创建资源。那为什么不呢。
  • 如果您的 REST 客户端以 PDF 格式 PUT/POST 资源,我猜您将无法提取正确创建/更新资源所需的所有信息。所以不行。

在最后一种情况下,您可能正在处理类似“Google 驱动器”的服务:这些 PDF 本身不是您的资源,应该由您的实际资源链接(即 URL 应该在您的资源中)。

即使 Google Drive 可能不是完美的 REST API (API 参考),它也同时处理 JSON 资源和实际的二进制文件。

于 2012-08-29T20:28:03.603 回答
3

根据我的经验,这样做与 REST Web 服务的想法背道而驰。与传统的 RESTful 服务不同,您永远无法缓存此响应而不引起严重的头痛。此外,由于您必须将服务作为文本使用才能读取 XML/JSON,因此您可能无法同时针对文本和二进制读取进行优化。更不用说,您必须始终需要二进制信息,否则当您只需要文本数据时,您的性能会受到相当大的影响。如果你总是需要二进制数据,不妨问问自己为什么需要网络服务?

这并不是说这是不可能的(毕竟有 BSON)或者不存在这种情况的用例,但是您应该非常确保在尝试之前无法强制单独请求二进制数据去做这个。将二进制数据嵌入到专为文本设计的文档格式中效率非常低,并且这种格式的数据将比原始字节大得多。

顺便说一句,如果您总是使用矢量图形资源(如 SVG 或某些类型的 PDF)来执行此操作,则可以将其表示为 XML 数据。同样,您可能不想这样做,因为它会增加您的有效负载,但它是解决“需要二进制文件”问题的一种选择。

于 2012-08-29T20:02:33.397 回答