I'm looking for an approach to move a blob in Azure from one container to another. The only solution I found is to use the Azure Storage Data Movement Library, but this seems to work between different accounts. I would like to move the blob within the same account to an other container.
3 Answers
I have not used Azure Storage Data Movement Library
but I am pretty sure that it will work in the same storage account as well.
Coming to your question, since Move
operation is not natively supported by Azure Storage what you can do is implement this by invoking Copy Blob
followed by Delete Blob
. In general Copy
operation is async however when a blob is copied in same storage account, it is a synchronous operation i.e. copy happens instantaneously. Please see sample code below which does just this:
static void MoveBlobInSameStorageAccount()
{
var cred = new StorageCredentials(accountName, accountKey);
var account = new CloudStorageAccount(cred, true);
var client = account.CreateCloudBlobClient();
var sourceContainer = client.GetContainerReference("source-container-name");
var sourceBlob = sourceContainer.GetBlockBlobReference("blob-name");
var destinationContainer = client.GetContainerReference("destination-container-name");
var destinationBlob = destinationContainer.GetBlockBlobReference("blob-name");
destinationBlob.StartCopy(sourceBlob);
sourceBlob.Delete(DeleteSnapshotsOption.IncludeSnapshots);
}
However, please keep in mind that you use this code only for moving blobs in the same storage account. For moving blobs across storage account, you need to ensure that copy operation is complete before you delete the source blob.

- 128,066
- 12
- 206
- 241
-
Worked great, but dear reader, you need `WIndowsAzure.Storage` nuget package. – Ronnie Overby Aug 15 '17 at 15:49
-
Will this incur egress and/or ingress charges? – Lukkha Coder Aug 15 '17 at 19:14
-
@LukkhaCoder If it is in the same storage account, you will not incur ingress/egress charges. You would however incur transaction charges associated with copy and delete operations. – Gaurav Mantri Aug 16 '17 at 03:02
-
@LukkhaCoder it will incur ingress/egress and transaction charges. Moreover, the provided code is wrong, since it is not waiting for copy completion which may result in data loss – lerthe61 Dec 03 '19 at 15:13
-
@lerthe61 The operation is synchronous and immediate if it's within the same storage account, which is a caveat mentioned in the answer. – Phillip Copley Oct 18 '21 at 16:34
-
@PhillipCopley [StartCopy](https://learn.microsoft.com/en-us/dotnet/api/microsoft.azure.storage.blob.cloudblockblob.startcopy?view=azure-dotnet-legacy) is asynchronous. Result has to be awaited before calling Delete on the sourceBlob. – lerthe61 Feb 02 '22 at 17:42
-
@lerthe61 Your link shows the return is a string. You can't await a string, and there is already a `StartCopyAsync` which is presumably the asynchronous version of the synchronous `StartCopy` – Phillip Copley Feb 15 '22 at 22:51
-
@PhillipCopley `StartCopy()` and `await StartCopyAsync()` return when operation is **started**. And even callback from `BeginStartCopy` is triggered when the operation is just started. This is why these methods has "Start" in their names. To check status of the operation you need to call `FetchAttributes()` periodically. String values that returns from this methods is called a Copy ID, and they can be used to abort operation by calling `AbortCopy` (or `AbortCopyAsync`). [Documentation](https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blob-copy?tabs=dotnet11#about-copying-blobs) – lerthe61 Mar 02 '22 at 22:13
-
[Topic 1](https://stackoverflow.com/questions/52503777/does-cloudblockblob-startcopyasync-return-when-the-copy-is-completed) [Topic 2](https://stackoverflow.com/questions/14152087/copying-one-azure-blob-to-another-blob-in-azure-storage-client-2-0/47651946#47651946) – lerthe61 Mar 02 '22 at 22:14
Here is what worked for me (answer edited after better answer by @Deumber was posted):
public async Task<CloudBlockBlob> Move(CloudBlockBlob srcBlob, CloudBlobContainer destContainer)
{
CloudBlockBlob destBlob;
if (srcBlob == null)
{
throw new Exception("Source blob cannot be null.");
}
if (!destContainer.Exists())
{
throw new Exception("Destination container does not exist.");
}
//Copy source blob to destination container
string name = srcBlob.Uri.Segments.Last();
destBlob = destContainer.GetBlockBlobReference(name);
await destBlob.StartCopyAsync(srcBlob);
//remove source blob after copy is done.
srcBlob.Delete();
return destBlob;
}

- 1,611
- 18
- 28
-
3Note to future readers: the user has edited this answer since the above comments were written and they are no longer applicable. – Richard Marskell - Drackir Nov 14 '17 at 14:09
-
2As noted in [Gaurav's answer](https://stackoverflow.com/a/40266588/33051) the copy option is not guaranteed to complete immediately - ["the Blob service copies blobs on a best-effort basis"](https://learn.microsoft.com/en-us/rest/api/storageservices/copy-blob#remarks). – Zhaph - Ben Duguid Jan 30 '19 at 12:46
-
Is there a way to get the virtual sub-directory to be copied over as well? It seems to be truncating that and just moving the raw blob itself and not creating the virtual directory structure on the other side. – stamm528 Nov 17 '19 at 13:23
-
@stamm528, I believe you will have to create the structure before, using the CloudBlobContainer.Exists() method, and if not exists, create. So you might edit this answer to take a 3rd parameter for directory structure. – Darrel K. Nov 18 '19 at 06:00
The answer accepted in this question will move the file to your server memory and then upload it from your memory to azure again.
A better practice could be let all the work on Azure
CloudBlobClient blobClient = StorageAccount.CreateCloudBlobClient();
CloudBlobContainer sourceContainer = blobClient.GetContainerReference(SourceContainer);
CloudBlobContainer targetContainer = blobClient.GetContainerReference(TargetContainer);
CloudBlockBlob sourceBlob = sourceContainer.GetBlockBlobReference(fileToMove);
CloudBlockBlob targetBlob = targetContainer.GetBlockBlobReference(newFileName);
await targetBlob.StartCopyAsync(sourceBlob);

- 850
- 9
- 18