如何使用AmazonS3.net sdk重命名存储桶中的文件夹

我知道s3并不真正支持文件夹概念。 复制/删除所有文件应该工作。 但也许有人知道一种更简单的方法(我只是没有在SDK中找到它)

更新/解决方案:

以下代码对我有用。

using (AmazonS3 client = Amazon.AWSClientFactory.CreateAmazonS3Client("xxx", "yyy")) { ListObjectsRequest listRequest = new ListObjectsRequest(); listRequest.WithBucketName("ytimusic") .WithPrefix("M" + oldOWnerId.ToString()+"/"); // get all objects inside the "folder" ListObjectsResponse objects = client.ListObjects(listRequest); foreach (S3Object s3o in objects.S3Objects) { // get the acl of the object GetACLRequest aclRequest = new GetACLRequest(); aclRequest.WithBucketName("thebucket") .WithKey(s3o.Key); GetACLResponse getAclResponse = client.GetACL(aclRequest); // copy the object without acl string newKey = s3o.Key.Replace(oldOWnerId.ToString(), newOwnerId.ToString()); CopyObjectRequest copyRequest = new CopyObjectRequest(); copyRequest.SourceBucket = "thebucket"; copyRequest.DestinationBucket = "thebucket"; copyRequest.WithSourceKey(s3o.Key) .WithDestinationKey(newKey); S3Response copyResponse = client.CopyObject(copyRequest); // set the acl of the newly created object SetACLRequest setAclRequest = new SetACLRequest(); setAclRequest.WithBucketName("ytimusic") .WithKey(newKey) .WithACL(getAclResponse.AccessControlList); SetACLResponse setAclRespone = client.SetACL(setAclRequest); DeleteObjectRequest deleteRequest = new DeleteObjectRequest(); deleteRequest.WithBucketName("thebucket") .WithKey(s3o.Key); DeleteObjectResponse deleteResponse = client.DeleteObject(deleteRequest); } } 

S3既不支持重命名也不支持文件夹,因此您实际上需要通过创建具有所需名称的副本并删除原始文件来单独处理每个文件。 要使用.NET SDK执行此操作,我担心没有比列出目录中的所有文件更简单的方法,并使用CopyObject + DeleteObject重命名每个文件。 另外,请注意,根据文档(http://docs.amazonwebservices.com/AmazonS3/latest/API/index.html?RESTObjectCOPY.html),复制操作不会保留ACL,因此如果移动的文件是公开的您还需要将副本明确标记为公开。

ListObjectResponse默认只返回1000个对象。 如果有超过1000个对象,则.IsTruncated属性设置为true。 您可以更改ListObjectsRequest标记以获取下一个1000个对象。 因此,如果重命名操作可能会影响超过1000个对象,则可以使用以下代码。

 public void MoveDirectory(string sourceKey, string destinationKey) { //Find all keys with a prefex of sourceKey, and rename them with destinationKey for prefix try { DeleteObjectsRequest deleteObjectsRequest = new DeleteObjectsRequest() { BucketName = bucket }; ListObjectsRequest listObjectsRequest = new ListObjectsRequest { BucketName = bucket, Prefix = sourceKey, }; do { ListObjectsResponse listObjectsResponse = client.ListObjects(listObjectsRequest); foreach (var s3Object in listObjectsResponse.S3Objects) { string newKey = s3Object.Key.Replace(sourceKey, destinationKey); CopyObjectRequest copyObjectRequest = new CopyObjectRequest() { SourceBucket = bucket, DestinationBucket = bucket, SourceKey = s3Object.Key, DestinationKey = newKey }; CopyObjectResponse copyObectResponse = client.CopyObject(copyObjectRequest); deleteObjectsRequest.AddKey(s3Object.Key); } if (listObjectsResponse.IsTruncated) { listObjectsRequest.Marker = listObjectsResponse.NextMarker; } else { listObjectsRequest = null; } } while (listObjectsRequest != null); client.DeleteObjects(deleteObjectsRequest); } catch (AmazonS3Exception amazonS3Exception) { Logger.Error("Error Occured with S3 MOVE", amazonS3Exception); } } 

我唯一可以看到使这个代码更好的方法是批量删除请求并一次性将其关闭。

  ListObjectsRequest listRequest = new ListObjectsRequest(); listRequest.WithBucketName(_bucket).WithPrefix(oldPath); DeleteObjectsRequest deleteRequest = new DeleteObjectsRequest(); deleteRequest.WithBucketName(_bucket); // GET ALL OBJECTS UNDER THIS "FOLDER" AND LOOP OVER THEM ListObjectsResponse listResponse = _client.ListObjects(listRequest); foreach (var obj in listResponse.S3Objects) { // GET THE ACCESS CONTROL LIST FROM THIS OBJECT BECAUSE COPY PROCEDURES DONT TAKE THIS INTO ACCOUNT GetACLRequest aclRequest = new GetACLRequest(); aclRequest.WithBucketName(_bucket).WithKey(obj.Key); GetACLResponse aclResponse = _client.GetACL(aclRequest); // GET THE NEW KEY AND COPY THIS OBJECT TO IT String newKey = obj.Key.Replace(oldPath, newPath); CopyObjectRequest copyRequest = new CopyObjectRequest { SourceBucket = _bucket, DestinationBucket = _bucket }; copyRequest.WithSourceKey(obj.Key).WithDestinationKey(newKey); CopyObjectResponse copyResponse = _client.CopyObject(copyRequest); // COPY OVER THE ACCESS CONTROL LIST TO THIS "NEW" OBJECT SetACLRequest setAclRequest = new SetACLRequest(); setAclRequest.WithBucketName(_bucket).WithKey(newKey).WithACL(aclResponse.AccessControlList); SetACLResponse setAclResponse = _client.SetACL(setAclRequest); // ADD THE OLD ITEM TO THE DELETE REQUEST deleteRequest.AddKey(obj.Key); } // DELETE ALL THE OLD OBJECTS IN ONE SHOT TO SAVE ON TRIPS BACK AND FORTH _client.DeleteObjects(deleteRequest);