lib*_*bik 140 rest json file-upload restful-architecture
我们正在使用REST API开发服务器,它接受并使用JSON进行响应.问题是,如果您需要将图像从客户端上传到服务器.
另请注意,我在讨论用例,其中实体(用户)可以拥有文件(carPhoto,licensePhoto),还有其他属性(名称,电子邮件...),但是当您创建新用户时,您不会发送这些图像,它们是在注册过程后添加的.
我所知道的解决方案,但每个都有一些缺陷
1.使用multipart/form-data而不是JSON
好:POST和PUT请求尽可能是RESTful,它们可以包含文本输入和文件.
缺点:它不再是JSON,与multipart/form-data相比,它更容易测试,调试等
2.允许更新单独的文件
用于创建新用户的POST请求不允许添加图像(在我们的用例中我在开始时的说法是可以的),上传图片是通过PUT请求作为multipart/form-data完成的,例如/ users/4/carPhoto
好的:一切(除了文件上传本身)都保留在JSON中,它很容易测试和调试(你可以记录完整的JSON请求而不用担心它们的长度)
缺点:它不直观,您不能一次POST或PUT实体的所有变量,并且此地址/users/4/carPhoto
可以更多地被视为一个集合(REST API的标准用例看起来像这样/users/4/shipments
).通常你不能(也不想)GET/PUT实体的每个变量,例如users/4/name.您可以使用GET获取名称,并在用户/ 4处使用PUT进行更改.如果在id之后有什么东西,它通常是另一个集合,比如users/4/reviews
3.使用Base64
将其作为JSON发送,但使用Base64编码文件.
good:与第一个解决方案相同,它尽可能地提供RESTful服务.
缺点:再次,测试和调试更糟糕(正文可以有兆字节数据),大小和处理时间都有所增加 - 客户端和服务器
我真的很想使用解决方案.2,但它有它的缺点...任何人都可以让我更好地了解"什么是最好的"解决方案?
我的目标是使用尽可能多的标准来提供RESTful服务,同时我希望尽可能简化它.
lib*_*bik 116
OP在这里(两年后我回答这个问题,Daniel Cerecedo的帖子一次都不错,但网络服务发展很快)
经过三年的全职软件开发(同时也关注软件架构,项目管理和微服务架构),我绝对选择第二种方式(但有一个通用端点)作为最佳方式.
如果您有图像的特殊端点,它将为您提供比处理图像更多的功能.
我们有两个相同的REST API(Node.js) - 移动应用程序(iOS/android)和前端(使用React).这是2017年,因此你不想存储图像localy,你想上传它们来云存储(谷歌云,s3,cloudinary,...),因此你想要一些一般处理它们.
我们的典型流程是,只要您选择图像,它就会开始在背景上上传(通常是POST在/ images端点上),上传后会返回ID.这实际上是用户友好的,因为用户选择图像然后通常继续其他一些字段(即地址,名称......),因此当他点击"发送"按钮时,图像通常已经上传.他不等着看屏幕说"上传......".
获取图像也是如此.特别是由于移动电话和有限的移动数据,你不想发送原始图像,你想发送调整大小的图像,所以他们不会采取那么多的数据(并使你的移动应用程序更快,你通常不想调整它的大小,你想要的图像完全适合你的视图).出于这个原因,好的应用程序正在使用像cloudinary(或者我们有自己的图像服务器来调整大小).
此外,如果数据不是私有的,那么您只需将URL发送回app/frontend URL,然后直接从云存储中下载,这样可以大大节省带宽和服务器的处理时间.在我们更大的应用程序中,每个月都会下载大量的TB,您不希望直接在每个REST API服务器上处理它,这些服务器专注于CRUD操作.您希望在一个地方(我们的Imageserver,它具有缓存等)处理它,或让云服务处理所有这些.
缺点:您应该想到的唯一"缺点"是"未分配图像".用户选择图像并继续填写其他字段,但随后他说"不"并关闭应用程序或标签,但同时您成功上传图像.这意味着您已上传未在任何地方分配的图像.
有几种方法可以解决这个问题.最简单的是"我不关心",这是相关的,如果这种情况不经常发生,或者你甚至希望存储用户发送给你的每个图像(出于任何原因),你不想要任何删除.
另一个也很容易 - 你有CRON,即每周你删除所有超过一周的未分配图像.
Dan*_*edo 90
有几个决定要做:
第一个关于资源路径:
将图像建模为资源:
嵌套在用户(/ user /:id/image)中:隐式地创建用户和图像之间的关系
在根路径(/ image)中:
客户负责建立图像与用户之间的关系,或者;
如果正在为用于创建映像的POST请求提供安全性上下文,则服务器可以隐式地在经过身份验证的用户和映像之间建立关系.
将图像作为用户的一部分嵌入
第二个决定是关于如何表示图像资源:
这将是我的决定轨道:
接下来的问题是:选择base64和multipart是否有任何性能影响?.我们可以认为以多部分格式交换数据应该更有效率.但是这篇文章表明两种表示在大小方面的差异很小.
我的选择Base64:
mmc*_*han 12
你的第二个解决方案可能是最正确的.您应该按照预期的方式使用HTTP规范和mimetypes,并通过上传文件multipart/form-data
.至于处理关系,我会使用这个过程(记住我对你的假设或系统设计一无所知):
POST
以/users
创建用户实体.POST
图像到/images
,确保Location
按照HTTP规范将标题返回到可以检索图像的位置.PATCH
到/users/carPhoto
并为其分配在给定照片的ID Location
步骤2的报头.没有简单的解决方案。每种方式都有其优缺点。但规范的方式是使用第一个选项:multipart/form-data
. 正如W3 推荐指南所说
内容类型“multipart/form-data”应用于提交包含文件、非 ASCII 数据和二进制数据的表单。
我们不是在发送表单,真的,但隐含的原则仍然适用。使用 base64 作为二进制表示是不正确的,因为您使用了不正确的工具来实现您的目标,另一方面,第二个选项迫使您的 API 客户端做更多的工作以使用您的 API 服务。您应该在服务器端努力工作,以提供易于使用的 API。第一个选项不容易调试,但当你这样做时,它可能永远不会改变。
使用multipart/form-data
您坚持 REST/http 哲学。您可以在此处查看类似问题的答案。
如果混合备选方案,另一种选择是,您可以使用 multipart/form-data 但不是单独发送每个值,您可以发送一个名为 payload 的值,其中包含 json 有效负载。(我使用 ASP.NET WebAPI 2 尝试了这种方法并且工作正常)。
归档时间: |
|
查看次数: |
86103 次 |
最近记录: |