简体   繁体   中英

Renaming a container/folder in azure blob storage

I am trying to rename a container name for users when a condition is met. I made some research and found out that there is no rename function for containers in azure blob storage. But there is a way to accomplish this by copying the files and deleting it after copy. Below is the code I made.

        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();

When I execute this code I got an error message. Below is the error.

Exception User-Unhandled Microsoft.WindowsAzure.Storage.StorageException:'The remote server returned an error: (404) Not Found.'

Inner Exception WebException: The remote server returned an error: (404) Not Found.

When I also try "blobNew.StartCopyAsync(blobOriginal)" the code just goes through but when I check the containers in azure there is no container created. What do you think the problem is? Any tips on how to improve my code? Delete function does not work also.

UPDATE I update my code and was able to copy the files from other to container to the new one. Below is the code.

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)));
}

AccessURI Method

 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;
    }

Now its working but another problem shows up. It says

System.InvalidCastException: 'Unable to cast object of type 'Microsoft.WindowsAzure.Storage.Blob.CloudBlobDirectory' to type 'Microsoft.WindowsAzure.Storage.Blob.CloudBlockBlob'.'

But this will be posted in another question. Thanks to our friend Gauriv for pointing out my problem. Check his answer below.

Update 2

By adding useFlatBlobListing: true in IEnumerable<IListBlobItem> IE = container.ListBlobs(blobListingDetails: BlobListingDetails.Metadata); I was able to fix my problem. This line of code was put in my display.

Final Code

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

If you look at your code for creating source and destination blob:

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

You'll notice that you're passing the names of the blob container and not the name of the blob. Because you don't have a blob in the container by the name of the container, you're getting 404 error.


To copy a blob container, what you have to do is list all blobs from the source container and then copy them individually in the destination container. Once all the blobs have been copied, you can delete the source container.

If you want, you can use Microsoft's Storage Explorer to achieve "rename container" functionality. It also works by copying blobs from old container to the renamed container and then deletes the old container.


    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.");
    }

You can rename containers with Microsoft's "Microsoft Azure Storage Explorer" (after version 0.8.3).

Actual Answer: Regarding your error message, If the client application receives an HTTP 404 (Not found) message from the server, this means that the object the client was attempting to use does not exist in the storage service. There are several possible reasons for this, such as:

· The client or another process previously deleted the object (Make sure name is correct)

· A Shared Access Signature (SAS) authorization issue

· Client-side code does not have permission to access the object

· Network failure

In order to identify the issue in detail, you can add a try/catch and see the actual error

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM