我想实现一个用于文件上传的REST API,它具有以下要求:
因此,要求1)和3)已经排除了使用多部分表格(我不喜欢这种方法)。
我已经有了一个满足要求1)的工作解决方案,首先发出POST
请求,将fileName
,fileSize
和fileModification
日期作为JSON传输。然后,上传模块会创建一个临时文件(如果不存在!)并以206
响应,其中包含标头中的上传令牌,而该令牌又是在POST
中发送的数据创建的哈希。此令牌必须用于实际上传。响应还包含一个字节范围,指示客户端必须上载文件的哪个部分。优点是,通过这种方式,如果以前的部分上传已经存在,则可以检测到 - 诀窍是将临时文件命名为与令牌相同。因此,字节范围也可能以另一个值0-
开头。恢复中断上传的所有用户都需要再次上传同一个文件!
实际上传是通过PUT
完成的,邮件正文仅包含原始二进制数据。然后,响应将返回所创建文件的元数据作为JSON,或以另一个206
响应,如果上载仍未完成,则包含更新的字节范围标头。因此,通过这种方式,也可以进行分块上传。总而言之,我喜欢这个解决方案并且效果很好。至少我没有看到在没有两阶段方法的情况下实施可恢复上传的其他方法。
现在,我的问题是让这真正“恢复”。
假设我们有一个名为/files
的集合,我想上传文件。当然,POST /files
似乎是这样做的自然方式。但是,我们会在同一个集合中有一个后续的PUT
,这在我看来当然不兼容REST。接下来的方法是初始POST
返回一个指向最终资源的新URL:/files/{fileId}
以及后续的PUT
(s)写入此资源。
感觉更“漂亮”,但不是那么简单,然后在上传未完成时可能存在不完整的文件资源。我认为只有在上传完成后才能创建实际资源。此外,如果我想稍后更新/添加元数据,那将是同一资源的PUT
,但请求本身会完全不同。嗯。
我可以将PUT
更改为POST
,因此上传内容会包含多个POST
,但这种情况也很可疑。
我还考虑过将资源拆分为两个子资源,例如/files/{fileId}/metadata
和/files/{fileId}/binary
,但这感觉有点“过度工程化”,并且还需要在上传完成之前创建文件资源。 / p>
如何以更好的方式解决这个问题?