我想为文件上传实现REST API,它具有以下要求:

  • 支持可恢复和分块上传

  • 支持在上传后添加和编辑元数据,如标签或说明

  • 资源友好,因此上传应该使用原始数据,即没有编码和/或封装

因此,要求1)和3)已经排除了使用多部分形式(我不喜欢这种方法) .

我已经有一个工作解决方案来满足要求1),首先发出一个 POST 请求,它将 fileNamefileSizefileModification 日期作为JSON发送 . 上传模块然后创建一个临时文件(如果不存在!)并以 206 响应,其中包含头部中的上传令牌,而该令牌又是在 POST 中发送的数据上创建的哈希 . 此令牌必须用于实际上载 . 响应还包含一个字节范围,指示客户端必须上载文件的哪个部分 . 优点是,通过这种方式,如果以前的部分上传已经存在,则可以检测到 - 诀窍是将临时文件命名为与令牌相同 . 所以字节范围也可能以另一个值 0- 开头 . 恢复中断上传的所有用户都要重新上传同一个文件!

实际上传是通过 PUT 完成的,消息体仅包含原始二进制数据 . 然后,响应将创建的文件的元数据作为JSON返回,或者如果上载仍然不完整,则使用包含更新的字节范围标头的另一个 206 进行响应 . 因此,通过这种方式,也可以进行分块上传 . 总而言之,我喜欢这个解决方案并且效果很好 . 至少我认为没有其他方法可以在没有2阶段方法的情况下实现可恢复上传 .

现在,我的问题是让这真正“恢复” .

假设我们有一个名为 /files 的集合,我想上传文件 . 当然, POST /files 似乎是这样做的自然方式 . 但是,接下来,我们会在同一个集合中使用 PUT ,这在我看来当然不兼容REST . 接下来的方法是初始 POST 返回一个指向最终资源的新URL: /files/{fileId} 以及随后的 PUT (s)写入此资源 .

感觉更多"RESTish",但不是那么简单,然后在上传未完成时可能存在不完整的文件资源 . 我认为只有在上传完成后才能创建实际资源 . 此外,如果我想稍后更新/添加元数据,那将是同一资源的 PUT ,但请求本身会完全不同 . 嗯 .

我可以将 PUT 更改为 POST ,因此上传将由多个 POST 组成,但这也有点腥味 .

我还想过将资源拆分为两个子资源,比如 /files/{fileId}/metadata/files/{fileId}/binary ,但这感觉有点"overengineered"并且还需要在上传完成之前创建文件资源 .

任何想法如何以更好的方式解决这个问题?