我正在尝试设计类似RESTful文件系统的服务,而复制/移动操作会给我带来一些麻烦。
首先,使用PUT到文件的最终URL上传新文件:
PUT /folders/42/contents/<name>
问题是,如果新文件已经在不同的URL下驻留在系统上怎么办?
复制/移动Idea 1 :使用自定义标头进行PUT。
这类似于S3's copy。 PUT看起来与上传相同,但带有自定义标题:
PUT /folders/42/contents/<name>
X-custom-source: /files/5
这很好,因为在复制/移动时很容易更改文件的名称。但是,S3不提供移动操作,可能是因为使用此方案的移动不是幂等的。
复制/移动Idea 2 :POST到父文件夹。
这类似于Google Docs copy。 POST目标文件夹,其中包含描述源文件的XML内容:
POST /folders/42/contents
...
<source>/files/5</source>
<newName>foo</newName>
我或许可以POST到文件的新URL来更改其名称..?否则,我不得不在XML内容中指定一个新名称,这会放大这个想法的RPCness。它也与想法1的上传操作不一致。
最终我正在寻找易于使用和理解的东西,所以除了对上述内容的批评之外,当然欢迎新的想法!
答案 0 :(得分:6)
要创建新资源,通常使用POST
。这应该在服务器创建的URI上创建一个新资源。
POST /folders/42/contents/fileName
<target>newFile</target>
REST说的是POST
新资源位于服务器确定的路径中。这就是复制甚至在(windows)文件系统中的工作方式。考虑将文件复制到已存在的名称,然后上述示例的响应可能是:
<newFileLocation>/folders/42/contents/newFile-2</newFileLocation>
然后通过第一次复制然后删除进行移动。您不应该在一个请求中执行这两个操作。
修改强>
我发现这本书RESTful Web Services Cookbook非常好。
第11章处理Copy方法,并在11.1中推荐以下内容:
问题您想知道如何制作现有资源的副本。
解决方案设计可以创建副本的控制器资源。客户端向此控制器发出POST请求以复制 资源。要使POST成为条件,请为其提供一次性URI 客户。控制器创建副本后,返回响应代码 201(已创建),其中包含副本的URI的Location标头。
请求 POST / albums / 2009/08 / 1011 / duplicate; t = a5d0e32ddff373df1b3351e53fc6ffb1
回复
<album xmlns:atom="http://www.w3.org/2005/Atom"> <id>urn:example:album:1014</id> <atom:link rel="self" href="http://www.example.org/albums/2009/08/1014"/> ... </album>
答案 1 :(得分:4)
HTTP规范说如果资源已经存在,那么您更新资源并返回200。 如果资源不存在,那么您创建它并返回201。
编辑:
好的,我误读了。我更喜欢POST到父文件夹的方法。您还可以使用查询字符串参数来引用源文件。 e.g。
POST /destination/folder?sourceFile=/source/folder/filename.txt
答案 2 :(得分:4)
REST不限于默认的HTTP方法集。在这种情况下你可以使用WebDAV。
答案 3 :(得分:0)
对于移动部分,如果要保持简单,只需复制(PUT)然后删除组合。
答案 4 :(得分:0)
移动时,你可以
A)。通过PUT复制自定义源标题,然后在源上删除。
B)。使用自定义移动标题删除源。
我更喜欢后者,因为它可以是原子的,客户很清楚资源是从原始集合中删除的。当它获取新位置的集合时,它将在那里找到移动的资源。