File 如何使用REST对文件系统操作建模?

File 如何使用REST对文件系统操作建模?,file,rest,filesystems,File,Rest,Filesystems,对于一些文件系统的基本操作(例如ls和rm),有明显的对应项,但是如何实现不直接的RESTful操作,例如cp或mv 正如对问题的回答所表明的,实现cp的首选方法包括获取资源、删除资源并使用新名称将其重新放回 但是如果我需要高效地完成它呢?例如,如果资源的大小很大?如何消除将资源的有效负载多余地传输到客户端并返回到原始服务器 这是一个例子。我有一个资源: /videos/my_videos/2-gigabyte-video.avi /videos/johns_videos/copied-2-gi

对于一些文件系统的基本操作(例如
ls
rm
),有明显的对应项,但是如何实现不直接的RESTful操作,例如
cp
mv

正如对问题的回答所表明的,实现
cp
的首选方法包括获取资源、删除资源并使用新名称将其重新放回

但是如果我需要高效地完成它呢?例如,如果资源的大小很大?如何消除将资源的有效负载多余地传输到客户端并返回到原始服务器

这是一个例子。我有一个资源:

/videos/my_videos/2-gigabyte-video.avi /videos/johns_videos/copied-2-gigabyte-video.avi /视频/my_videos/2-gigabyte-video.avi 我想把它复制到一个新的资源中:

/videos/my_videos/2-gigabyte-video.avi /videos/johns_videos/copied-2-gigabyte-video.avi /视频/johns_视频/copied-2-gigabyte-video.avi
如何以RESTful方式实现复制、移动或其他文件系统操作?还是有一个合适的方法?我做错了吗?

在我看来,视频是一种资源。所以这个资源有一个路径。如果您执行的更新更改了资源路径,该怎么办


然后,在您的代码中,如果更改了路径,您只需移动文件。

一种方法是制定PUT/POST请求,这样您就可以提供实际数据或资源的URL,可能还可以选择进行硬链接或符号链接。如果给定的URL托管在您自己的系统上,那么您可以简单地在内部指向同一个文件,可能会保留一点“写时复制”或类似的内容,以提高效率

[…首选的实施方式 cp将包括获取资源, 删除它并将其重新放回 使用新名称。]

上述方法的一个问题是缺乏原子性和一致性。由于每个操作(GET、DELETE和PUT)都是通过HTTP(本质上是无状态的)进行的,因此服务器无法强制实现原子性。出于任何原因,客户机可能会在最后一步之前的任何步骤后中止,这将使服务器的数据状态不一致

一种可能的方法:

  • 如果这些资源是文档(我猜,在您的案例中就是这样),我会探索使用它们的选项
  • 如果WebDAV不是一个选项--
    • 在服务器上创建控制器对象以管理复制和移动操作,客户端可以发布到/videos/my\u videos/[video\u id]/copy之类的内容
    • 在响应中,您可以在以下行中指定复制资源的URI:
HTTP/1.1201已创建

内容类型:视频/x-msvideo

位置:/videos/johns_videos/8765

注意:我更喜欢发送一个ID并使用资源ID,而不是类似的东西

地点: /视频/johns_视频/copied-2-gigabyte-video.avi

移动操作非常类似,只是服务器可以接受目标资源。例如:


您可以扩展上述方法,以便服务器向客户机发送最后修改的标记,客户机将其与请求一起发送。只有当该值仍然一致时,服务器才会执行复制/移动操作。这将解决在复制/移动操作仍在进行时更改资源的并发性问题

您可以公开一个新服务,该服务包含(发布)一个简单的xml文档,该文档概述了您想要做的事情

<move>
   <target>/videos/my_videos/2-gigabyte-video.avi</target>
   <destination>/videos/johns_videos/copied-2-gigabyte-video.avi<destination>
<move>

/视频/my_videos/2-gigabyte-video.avi
/视频/johns_视频/copied-2-gigabyte-video.avi

然后,该服务可以返回一个URI,客户端可以在其中检查操作的状态。然后,客户端可以与该新资源交互,说如果仍挂起则取消移动,或者检查移动是否成功。

REST不限于HTTP!最好的方法是使用webdav解决您的问题。

我不相信给出的任何答案都是RESTful。这就是我要做的

副本:

PUT /videos/johns_videos/copied-2-gigabyte-video.avi
HOST: www.server.com
Content-Location: /videos/johns_videos/2-gigabyte-video.avi
[empty-body]
将内容放在(/videos/johns_videos/2-gigabyte-video.avi)的位置(/videos/johns_videos/copied-2-gigabyte-video.avi)

移动将是带有删除的副本,为了检查副本和删除之间的一致性,您需要使用PUT回复中提供给您的修订号

PUT /videos/johns_videos/copied-2-gigabyte-video.avi
HOST: www.server.com
Content-Location: /videos/johns_videos/2-gigabyte-video.avi
[empty-body]

    201 Created
    ETag: "3e32f5a1123afb12" (an md5 of the file)
    Location: /videos/johns_videos/copied-2-gigabyte-video.avi
    [empty-body]

DELETE /videos/johns_videos/2-gigabyte-video.avi
HOST: www.server.com
If-Match: "3e32f5a1123afb12"
[empty-body]

    204 No Content
    [empty-body]
为什么这么安静

  • 不将“移动”或“复制”附加到URI(即RPC)上
  • 它使用PUT(POST是附加到集合的,目标URI不是完全已知的)
  • 它不使用RPC而不是REST发送的“命令”(例如XML指令)
  • 不了解下划线存储-客户不关心硬/软链接或写在拷贝上的优化,永远不应该知道它们

迈克·布朗(Mike Brown)

但这不意味着你正在将操作的含义编码到消息中吗?一点也不。您的消息正在改变系统的状态,这实际上是HATEOAS的定义。你怎么能写出一条毫无意义的信息?好吧,我明白你的意思了。我只是不太愿意在消息中编码操作,因为它让我想起了RPC风格的web服务(例如SOAP),在SOAP中,您将操作(移动)封装在信封中,并将其发送到通用端点。理解这类消息含义的唯一方法是对其进行解析并理解其语义,这似乎不是很平静。再说一次,如果我只使用四个基本的HTTP动词,可能没有完美的解决方案。这与大家经常引用的类“RESTbucks-如何RESTfully点一杯咖啡”(或其他什么)没有什么不同。您正在向队列提交作业,并返回响应(以及指向其他资源的链接)。您的客户只需要了解您定义的超媒体格式,然后按照链接的数据图进行操作即可获得结果。我喜欢您的方法-我会看看是否可以利用Webd