问题
I am trying to rename a container in azure blob storage. I was able to successfully rename the container. But I noticed in some few cases that during some process. I encountered some error.
Here is the error message.
System.InvalidCastException: 'Unable to cast object of type 'Microsoft.WindowsAzure.Storage.Blob.CloudBlobDirectory' to type 'Microsoft.WindowsAzure.Storage.Blob.CloudBlockBlob'.'
Below is my code.
string ContainerName = "old-container-name";
string NewContainerName = "new-container-name";
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(blobListingDetails: BlobListingDetails.Metadata);
foreach (IListBlobItem item in IE)
{
CloudBlockBlob blob = (CloudBlockBlob)item;
CloudBlockBlob destBlob = destcontainer.GetBlockBlobReference(blob.Name);
destBlob.StartCopyAsync(new Uri(GetSharedAccessUri(blob.Name, container)));
}
I received the error on this line:
CloudBlockBlob blob = (CloudBlockBlob)item;
Do you guys have a fix on this one? Any tips on how to fix this?
回答1:
The reason you're getting this error is because of the way you're listing the blobs.
IEnumerable<IListBlobItem> IE = container.ListBlobs(blobListingDetails: BlobListingDetails.Metadata);
Above line of code will list both blobs and virtual folders. Virtual folders are represented by CloudBlobDirectory
. Since you're trying to cast an object of type CloudBlockBlob
as CloudBlobDirectory
, you're getting this exception.
To list all blobs in a blob container, please use the following override of ListBlobs
method: https://docs.microsoft.com/en-us/dotnet/api/microsoft.azure.storage.blob.cloudblobcontainer.listblobs?view=azure-dotnet-legacy.
You will need to pass true
for useFlatBlobListing
parameter. It will then return only the blobs and not virtual folders.
回答2:
- Check the type of
item
before casting. - You must
await
yourTask
. - Always prefer the Async API. Don't mix non-Async and Async APIs (this does mean using the custom
ListBlobsAsync
method also defined below as there is no singleListBlobsAsync
method):
async Task CopyBlobsAsync()
{
const String ContainerName = "old-container-name";
const String NewContainerName = "new-container-name";
CloudStorageAccount storageAccount = CloudStorageAccount.Parse( CloudConfigurationManager.GetSetting("StorageConnectionString") );
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference( ContainerName );
CloudBlobContainer destcontainer = blobClient.GetContainerReference( NewContainerName );
await destcontainer.CreateIfNotExistsAsync( BlobContainerPublicAccessType.Blob );
List<IListBlobItem> blobs = await ListBlobsAsync( container ).ConfigureAwait(false);
List<Task> tasks = new List<Task>();
foreach( IListBlobItem item in blobs )
{
if( item is CloudBlockBlob blob )
{
CloudBlockBlob destBlob = destcontainer.GetBlockBlobReference( blob.Name );
Uri destUri = new Uri( GetSharedAccessUri( blob.Name, container ) );
Task task = destBlob.StartCopyAsync( destUri );
tasks.Add( task );
}
}
await Task.WhenAll( tasks ).ConfigureAwait(false);
}
// From https://ahmet.im/blog/azure-listblobssegmentedasync-listcontainerssegmentedasync-how-to/
async Task<List<IListBlobItem> ListBlobsAsync( CloudBlobContainer container )
{
BlobContinuationToken continuationToken = null;
List<IListBlobItem> results = new List<IListBlobItem>();
do
{
var response = await ListBlobsSegmentedAsync( continuationToken );
continuationToken = response.ContinuationToken;
results.AddRange( response.Results );
}
while( continuationToken != null );
return results;
}
来源:https://stackoverflow.com/questions/59150291/system-invalidcastexception-in-renaming-azure-container