HTTP部分上传,恢复上传的标准方法

时间:2014-01-07 10:32:40

标签: http upload

我正在开发http客户端/服务器框架,并寻找处理部分上传的正确方法(与使用带有Range标头的GET方法的下载相同)。

但是,HTTP PUT不打算恢复。 据我所知,PATCH方法并不接受Range标头。

有没有办法通过HTTP标准处理这个问题(不使用扩展标题或其他)?

提前致谢。

4 个答案:

答案 0 :(得分:9)

我认为部分上传没有标准:

  • 内容 - 请求内部的请求未在RFC2616(http)中明确禁止,但措辞也将其称为响应标头,用于响应范围请求
  • 虽然您可以使用PATCH方法更新现有资源(例如添加更多字节),但它与部分上传不同,因为所有时间都不完整资源可用

如果你看看Dropbox,谷歌驱动器等的协议,他们都会推出自己的协议,以便在多个块中传输单个文件。您可恢复上传所需的是

  • 解决不完整上传的方法。普通URL可以处理完整的资源,而不是部分资源,我知道部分资源没有标准。
  • 一种查找上传当前状态的方法,也可能是该部分的校验和,以确保本地文件没有改变。这可以通过WebDAV PROPFIND方法提供(一旦你能够解决不完整的资源:)
  • 上传大块的方法。这里可以使用PATCH和内容范围标题。 mod_dav似乎允许PUT使用内容范围标题(请参阅http://www.gossamer-threads.com/lists/apache/users/432346
  • 一种在资源完成后发布资源的方法,或者预先定义完整资源的方式(例如资源大小,校验和......)

答案 1 :(得分:1)

正如一些评论中所指出的,HTTP规范的较新版本在某种程度上澄清了这一点。每Section 4.3.4 of RFC 7231

  

允许PUT在给定目标资源上的原始服务器必须发送   对包含a的PUT请求的400(错误请求)响应   内容范围标头字段(Section 4.2 of [RFC7233]),因为有效负载   很可能是部分内容被错误地作为一个完整的PUT   表示。通过定位a,可以进行部分内容更新   单独识别的资源与状态重叠的部分   更大的资源,或者使用具体的不同方法   为部分更新定义(例如,在中定义的PATCH方法)   [RFC5789])。

不幸的是,RFC 7233中出现的范围标题的讨论或多或少完全集中在GET请求上,RFC 5789几乎没有定义任何关于PATCH的内容,除了特别不需要传输整个内容(但是被允许),也不是必须是幂等的(但是被允许)。

好的一面是因为PATCH的定义过于宽松,所以它确实适应了相关问题(https://stackoverflow.com/a/6711496/7467189)中给出的方法:只需将“PUT”改为“PATCH”即可。虽然不要求服务器以这种方式解释具有Content-Range头的PATCH请求,但它肯定是有效的解释,而不是任何可以依赖于任意服务器或客户端的解释。但在原始问题的情况下,如果可以控制两端,则至少是一种明显的方法,并且不违反现行标准。

另一个考虑因素是Content-Type应该表达正在传输的内容,而不是整个实体的内容类型(RFC在这方面提供了一些示例)。对于以任意块“修补”的内容,这将意味着应用程序/八位字节流,尽管有些情况下客户端和服务器可能更具内容感知并且选择将补丁作为具有更具体定义的实体发送(例如,单页多页图像格式。)

答案 2 :(得分:1)

使用Range xxxx-yyyy标头或带有PUT的Range xxxx-标头来更新文件的一部分。它受Apache支持。

不要对RFC 7231中的语句感到困惑,即不能使用Content-Range。这是为了防止客户端从服务器接收标头并使用PUT将它们发送回服务器。该警告通知与部分PUT问题无关。

答案 3 :(得分:1)

PATCH将是为可恢复的上传选择的一种逻辑方法:它需要一种指示如何更改目标资源的媒体类型。尽管multipart/byteranges并未明确定义为执行修补的格式,但它指定了字节范围和该范围的内容,从而使其对于PATCH有效负载已适当定义。

示例:

PATCH /document HTTP/1.1
Content-Type: multipart/byteranges; boundary=THIS_STRING_SEPARATES

--THIS_STRING_SEPARATES
Content-Type: text/plain
Content-Range: bytes 10-21/22

1234567890
--THIS_STRING_SEPARATES--

此示例以十字节的偏移量上传十二个字节。 THIS_STRING_SEPARATES是用户选择的任意定界符,应随机生成。为了简洁起见,省略了一些标头,每行以terminated结尾。