实现RESTful大文件上传的正确方法
Posted
技术标签:
【中文标题】实现RESTful大文件上传的正确方法【英文标题】:Proper way to implement RESTful large file upload 【发布时间】:2016-02-26 15:26:39 【问题描述】:我制作 REST API 已经有一段时间了,但我仍然对一种情况感到困扰 - 大文件上传。我已经阅读了其他一些 API,例如 Google Drive、Twitter 和其他文献,我有两个想法,但我不确定它们中的任何一个是否“正确”。正如正确的那样,我的意思是它有点标准化,不需要太多的客户端逻辑(因为其他方将实现该客户端),或者更好的是,它可以很容易地用 cURL 调用。计划是在 Java 中实现它,最好是 Play Framework。
显然我需要一些文件分区和服务器端缓冲机制,因为文件很大。
所以,我得到的第一个解决方案是分段上传 (multipart/form-data
)。我是这样实现的,我以前也这样实现过,但是在客户端实际模拟一个表单对我来说总是很奇怪,特别是因为客户端必须设置文件键名,根据我的经验,这是客户有点忘记或不理解。另外,块大小/部分大小是如何规定的?是什么阻止了客户端将整个文件放在一个块中?
解决方案二,至少我所理解的,但没有找到实际的实现实现是“常规” POST 请求可以工作。内容应该被分块并且数据在服务器端被缓冲。但是,我不确定这是一个正确的理解。数据实际上是如何分块的,上传是跨越多个 HTTP 请求还是在 TCP 级别上分块? Content-Type
是什么?
最重要的是,这两个(或其他什么?)应该是一种客户端友好、易于理解的实现文件上传 REST API 的方式?
【问题讨论】:
我建议复制 YouTube resumable upload protocol。他们每天使用这种格式处理令人费解的数据量,所以我认为它运作良好。 【参考方案1】:我建议您查看 Amazon S3 Rest API 的多部分文件上传解决方案。可以在here找到文档。
总结亚马逊使用的程序:
客户端发送请求发起分段上传,API响应上传id
客户端上传每个文件块,带有一个part number(保持文件的顺序),part的大小,part的md5 hash和upload id;这些请求中的每一个都是一个单独的 HTTP 请求。 API 通过检查收到的 md5 散列与客户端提供的 md5 散列来验证块,并且块的大小与客户端提供的大小匹配。 API 使用块的标签(唯一 ID)进行响应。如果您在多个位置部署 API,您将需要考虑如何存储这些块,然后以一种位置透明的方式访问它们。
客户端发出完成上传的请求,其中包含从 API 接收的每个块编号和相关块标记(唯一 id)的列表。 API 验证没有丢失的块,并且块编号与正确的块标签匹配,然后组装文件或返回错误响应。
亚马逊还提供中止上传和列出与上传相关的块的方法。您可能还需要考虑上传请求的超时,如果上传未在一定时间内完成,则会在该超时期间销毁块。
在控制客户端上传的块大小方面,您无法控制客户端如何决定拆分上传。您可以考虑为上传配置最大块大小,并为包含大于最大大小的块的请求提供错误响应。
我发现该过程非常适用于处理 REST API 中的大文件上传,并有助于处理与文件上传相关的许多边缘情况。不幸的是,我还没有找到一个库可以让任何语言都轻松实现这一点,因此您几乎必须自己编写所有逻辑。
【讨论】:
我正在考虑做同样的事情,但我想知道对于服务器合并文件的最后一个 API,它不会花费太长时间并且不会定时 HTTP 连接出去? 好点。可能最好只进行块验证并在组装继续时返回 202。【参考方案2】:https://tus.io/ 是可恢复协议,有助于块上传和超时后恢复上传。这是一个开源实现,并且已经有不同语言的各种客户端和服务器实现。
【讨论】:
以上是关于实现RESTful大文件上传的正确方法的主要内容,如果未能解决你的问题,请参考以下文章