重命名 Azure Blob 存储中的容器/文件夹



我正在尝试在满足条件时为用户重命名容器名称。我做了一些研究,发现 azure blob 存储中的容器没有重命名功能。但是有一种方法可以通过复制文件并在复制后删除它来实现这一点。下面是我制作的代码。

string ContainerName = "old-container-name-user1";
string NewContainerName = "new-container-name-user2"
CloudStorageAccount sourceAccount = CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("StorageConnectionString"));
CloudBlobClient sourceblobClient = sourceAccount.CreateCloudBlobClient();
CloudBlobContainer sourceBlobContainer = sourceblobClient.GetContainerReference(ContainerName);
CloudBlobContainer destBlobContainer = sourceblobClient.GetContainerReference(NewContainerName);
CloudBlockBlob blobOriginal = sourceBlobContainer.GetBlockBlobReference(ContainerName);
CloudBlockBlob blobNew = destBlobContainer.GetBlockBlobReference(NewContainerName);
blobNew.StartCopy(blobOriginal);
blobOriginal.Delete();

当我执行此代码时,我收到一条错误消息。下面是错误。

异常用户未处理 Microsoft.WindowsAzure.Storage.StorageException:"远程服务器 返回错误:(404( 未找到。

内部异常 Web 异常:远程服务器返回错误: (404( 未找到。

当我也尝试"blobNew.StartCopyAsync(blobOriginal("时,代码只是通过,但是当我检查Azure中的容器时,没有创建容器。你认为问题是什么?关于如何改进我的代码的任何提示?删除功能也不起作用。

更新我更新了我的代码,并能够将文件从其他容器复制到新容器。下面是代码。

string ContainerName = "old-container-name-user1"
string NewContainerName = "new-container-name-user2"
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("StorageConnectionString"));
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference(ContainerName);
CloudBlobContainer destcontainer = blobClient.GetContainerReference(NewContainerName);
destcontainer.CreateIfNotExists(BlobContainerPublicAccessType.Blob);
IEnumerable<IListBlobItem> IE = container.ListBlobs(useFlatBlobListing: true);
foreach (IListBlobItem item in IE)
{
CloudBlockBlob blob = (CloudBlockBlob)item;
CloudBlockBlob destBlob = destcontainer.GetBlockBlobReference(blob.Name);
destBlob.StartCopyAsync(new Uri(GetSharedAccessUri(blob.Name, container)));
}

访问URI方法

private static string GetSharedAccessUri(string blobName, CloudBlobContainer container)
{
DateTime toDateTime = DateTime.Now.AddMinutes(60);
SharedAccessBlobPolicy policy = new SharedAccessBlobPolicy
{
Permissions = SharedAccessBlobPermissions.Read,
SharedAccessStartTime = null,
SharedAccessExpiryTime = new DateTimeOffset(toDateTime)
};
CloudBlockBlob blob = container.GetBlockBlobReference(blobName);
string sas = blob.GetSharedAccessSignature(policy);
return blob.Uri.AbsoluteUri + sas;
}

现在它的工作,但出现了另一个问题。它说

System.InvalidCastException: '无法强制转换类型的对象 "Microsoft.WindowsAzure.Storage.Blob.CloudBlobDirectory"键入 'Microsoft.WindowsAzure.Storage.Blob.CloudBlockBlob'."

但这将在另一个问题中发布。感谢我们的朋友高里夫指出我的问题。在下面查看他的答案。

更新 2

通过在IEnumerable<IListBlobItem> IE = container.ListBlobs(blobListingDetails: BlobListingDetails.Metadata);中添加useFlatBlobListing: true,我能够解决我的问题。这行代码放在我的显示器中。

最终代码

IEnumerable<IListBlobItem> IE = container.ListBlobs(blobListingDetails: BlobListingDetails.Metadata, useFlatBlobListing: true);

如果查看用于创建源和目标 blob 的代码:

CloudBlockBlob blobOriginal = sourceBlobContainer.GetBlockBlobReference(ContainerName);
CloudBlockBlob blobNew = destBlobContainer.GetBlockBlobReference(NewContainerName);

你会注意到,你传递的是 Blob 容器的名称,而不是 Blob 的名称。由于容器中没有容器名称的 Blob,因此会收到 404 错误。

若要复制 Blob 容器,

只需列出源容器中的所有 Blob,然后在目标容器中单独复制它们。复制所有 Blob 后,可以删除源容器。

如果需要,可以使用Microsoft的存储资源管理器来实现"重命名容器"功能。它还通过将 Blob 从旧容器复制到重命名的容器,然后删除旧容器来工作。


static void RenameContainer()
{
var connectionString = "DefaultEndpointsProtocol=https;AccountName=account-name;AccountKey=account-key";
var storageAccount = CloudStorageAccount.Parse(connectionString);
var client = storageAccount.CreateCloudBlobClient();
var sourceContainer = client.GetContainerReference("source-container");
var targetContainer = client.GetContainerReference("target-container");
targetContainer.CreateIfNotExists();//Create target container
BlobContinuationToken continuationToken = null;
do
{
Console.WriteLine("Listing blobs. Please wait...");
var blobsResult = sourceContainer.ListBlobsSegmented(prefix: "", useFlatBlobListing: true, blobListingDetails: BlobListingDetails.All, maxResults: 1000, currentToken: continuationToken, options: new BlobRequestOptions(), operationContext: new OperationContext());
continuationToken = blobsResult.ContinuationToken;
var items = blobsResult.Results;
foreach (var item in items)
{
var blob = (CloudBlob)item;
var targetBlob = targetContainer.GetBlobReference(blob.Name);
Console.WriteLine(string.Format("Copying "{0}" from "{1}" blob container to "{2}" blob container.", blob.Name, sourceContainer.Name, targetContainer.Name));
targetBlob.StartCopy(blob.Uri);
}
} while (continuationToken != null);
Console.WriteLine("Deleting source blob container. Please wait.");
//sourceContainer.DeleteIfExists();
Console.WriteLine("Rename container operation complete. Press any key to terminate the application.");
}

可以使用Microsoft的"Microsoft Azure 存储资源管理器"(版本 0.8.3 之后(重命名容器。

实际答案:关于错误消息,如果客户端应用程序从服务器收到 HTTP 404(未找到(消息,这意味着客户端尝试使用的对象在存储服务中不存在。这有几个可能的原因,例如:

· 客户端或其他进程之前删除了对象(确保名称正确(

· 共享访问签名 (SAS( 授权问题

· 客户端代码无权访问对象

· 网络故障

为了详细识别问题,您可以添加 try/catch 并查看实际错误

最新更新