【发布时间】:2012-08-24 12:13:27
【问题描述】:
使用 REST API 交付二进制资源(如 pdf 文件)的惯例是什么?您是否只是在 JSON 或 XML 响应中返回资源的 URL,例如 {"url" : "http://example.com/document.pdf"} ?
我试图理解 URI 和 URL 之间的区别,并保持 RESTful 哲学。诚然,这对我来说是新的,所以我可能会误解一些事情。
【问题讨论】:
标签: rest
使用 REST API 交付二进制资源(如 pdf 文件)的惯例是什么?您是否只是在 JSON 或 XML 响应中返回资源的 URL,例如 {"url" : "http://example.com/document.pdf"} ?
我试图理解 URI 和 URL 之间的区别,并保持 RESTful 哲学。诚然,这对我来说是新的,所以我可能会误解一些事情。
【问题讨论】:
标签: rest
URI 和 URL 之间的区别与二进制与非二进制数据类型没有任何关系 (see also)。
如果您返回的主要是 JSON,那么 url 条目是一种常见的方法。如果您正在做一些更类似于 HTML/XML 的事情,那么像 <link> 元素这样具有良好的 rel 属性的东西很有意义。
显然,如果客户端向您提供给他们的直接 URL 发出 GET 请求,那么您应该将文件发送给他们,除非他们发送了一堆内容协商标头,从而有效地阻止您完成他们的请求。在这种情况下,406 Not Acceptable 响应(或 the official definition)很有意义。
如果您的问题是其他意思,请澄清。
首先:忽略 URL 与 URI。它与此无关。完全没有。
下一步:如果您的问题不是“我如何链接到资源”(这可能会受到我将要讨论的内容的影响),而是“如果我的资源只是一个 PDF 文件怎么办”,那么您有解决它的各种选项。首先,你需要退后一步,更抽象地思考(一点点)。您的资源几乎肯定不是“PDF 文件”。它是“用户上传的文件”,或“我生成的 PDF 版本的报告”等。
在第一种情况下,除了他们发送给您的二进制文件之外,您可能没有任何资源表示,这完全没问题。当您收到指向该资源 URL 的 GET 时,您可能不需要执行任何类型的内容协商。只需将文件发送给他们,但要遵守我上面提到的关于 406 的警告。
在第二种情况下,您可能拥有该资源的各种表示形式:CSV、HTML、LaTeX,应有尽有。在这种情况下,当您收到指向资源 URL 的 GET 时,您确实需要进行一些内容协商,以便知道是否向他们发送 PDF 文档或其他内容。您可能拥有资源的 JSON 表示形式,它只是您用于生成 PDF 的原始数据。
在任何一种情况下,如果您有一个完全是关于资源的元数据的表示,那将是出乎意料的。如果需要(通常是,有时不是),显式的外部元数据(与嵌入在二进制资源中的元数据相反,例如 PDF 中的作者和标题信息)最常被建模为单独的资源。
最后,正如@monitorjbl 所说:您可能不希望将二进制数据直接嵌入文本格式,例如 JSON 或 XML。有很多方法可以做到这一点,通常涉及“base64-encoded”这个词,但这通常不是最好的方法。一般来说,您不应该混合使用二进制数据和文本数据。
【讨论】:
无论是否二进制,您的 REST 资源都应使用超媒体类型进行描述。
在最后一种情况下,您可能正在处理类似“Google 驱动器”的服务:这些 PDF 本身不是您的资源,应该由您的实际资源链接(即 URL 应该在您的资源中)。
即使 Google Drive 可能不是完美的 REST API (API reference),它也同时处理 JSON 资源和实际的二进制文件。
【讨论】:
根据我的经验,这样做与 REST Web 服务的想法背道而驰。与传统的 RESTful 服务不同,您永远无法缓存此响应而不引起严重的头痛。此外,由于您必须将服务作为文本使用才能读取 XML/JSON,因此您可能无法同时针对文本和二进制读取进行优化。更不用说,您必须始终 需要二进制信息,否则当您只需要文本数据时,性能会受到相当大的影响。如果您总是需要二进制数据,不妨问问自己为什么需要网络服务?
这并不是说这是不可能的(毕竟有 BSON)或者不存在这种情况的用例,但是您应该非常确保您无法逃避对二进制数据的单独请求在您尝试执行此操作之前。将二进制数据嵌入到专为文本设计的文档格式中效率非常低,并且这种格式的数据会比原始字节大得多。
顺便说一句,如果您总是使用矢量图形资源(如 SVG 或某些类型的 PDF)执行此操作,则可以将其表示为 XML 数据。同样,您可能不想这样做,因为它会增加您的有效负载,但它是解决“需要二进制文件”问题的一种选择。
【讨论】: