/// <summary> /// Copy data between Azure storage. /// 1. Copy a CloudBlobDirectory /// 2. Cancel the transfer before it finishes with a CancellationToken /// 3. Store the transfer checkpoint into a file after transfer being cancelled /// 4. Reload checkpoint from the file /// 4. Resume the transfer with the loaded checkpoint /// </summary> private static async Task BlobDirectoryCopySample() { CloudBlobDirectory sourceBlobDir = Util.GetCloudBlobDirectory(ContainerName, "blobdir"); CloudBlobDirectory destBlobDir = Util.GetCloudBlobDirectory(ContainerName, "blobdir2"); // When source is CloudBlobDirectory: // 1. If recursive is set to true, data movement library matches the source blob name against SearchPattern as prefix. // 2. Otherwise, data movement library matches the blob with the exact name specified by SearchPattern. // // You can also replace the source directory with a CloudFileDirectory instance to copy data from Azure File Storage. If so: // 1. If recursive is set to true, SearchPattern is not supported. Data movement library simply transfer all azure files // under the source CloudFileDirectory and its sub-directories. // 2. Otherwise, data movement library matches the azure file with the exact name specified by SearchPattern. // // In the following case, data movement library will copy all blobs with the prefix "azure" in source blob directory. CopyDirectoryOptions options = new CopyDirectoryOptions() { SearchPattern = "azure", Recursive = true, }; TransferContext context = new TransferContext(); context.FileTransferred += FileTransferredCallback; context.FileFailed += FileFailedCallback; context.FileSkipped += FileSkippedCallback; // Create CancellationTokenSource used to cancel the transfer CancellationTokenSource cancellationSource = new CancellationTokenSource(); TransferCheckpoint checkpoint = null; try { Task task = TransferManager.CopyDirectoryAsync(sourceBlobDir, destBlobDir, false /* isServiceCopy */, options, context, cancellationSource.Token); // Sleep for 1 seconds and cancel the transfer. // It may fail to cancel the transfer if transfer is done in 1 second. If so, no file will be copied after resume. Thread.Sleep(1000); Console.WriteLine("Cancel the transfer."); cancellationSource.Cancel(); await task; } catch (Exception e) { Console.WriteLine("The transfer is cancelled: {0}", e.Message); } // Store the transfer checkpoint checkpoint = context.LastCheckpoint; // Serialize the checkpoint into a file IFormatter formatter = new BinaryFormatter(); string tempFileName = Guid.NewGuid().ToString(); using (var stream = new FileStream(tempFileName, FileMode.Create, FileAccess.Write, FileShare.None)) { formatter.Serialize(stream, checkpoint); } // Deserialize the checkpoint from the file using (var stream = new FileStream(tempFileName, FileMode.Open, FileAccess.Read, FileShare.None)) { checkpoint = formatter.Deserialize(stream) as TransferCheckpoint; } File.Delete(tempFileName); // Create a new TransferContext with the store checkpoint TransferContext resumeContext = new TransferContext(checkpoint); resumeContext.FileTransferred += FileTransferredCallback; resumeContext.FileFailed += FileFailedCallback; resumeContext.FileSkipped += FileSkippedCallback; // Record the overall progress ProgressRecorder recorder = new ProgressRecorder(); resumeContext.ProgressHandler = recorder; // Resume transfer from the stored checkpoint Console.WriteLine("Resume the cancelled transfer."); await TransferManager.CopyDirectoryAsync(sourceBlobDir, destBlobDir, false /* isServiceCopy */, options, resumeContext); // Print out the final transfer state Console.WriteLine("Final transfer state: {0}", recorder.ToString()); }
/// <summary> /// Download data from Azure storage. /// 1. Download a CloudBlob to an exsiting local file /// 2. Query the user to overwrite the local file or not in the OverwriteCallback /// 3. Download another CloudBlob to local with content MD5 validation disabled /// 4. Show the overall progress of both transfers /// </summary> private static async Task BlobDownloadSample() { string sourceBlobName1 = "azure_blockblob.png"; string sourceBlobName2 = "azure_blockblob2.png"; string destinationFileName1 = "azure.png"; string destinationFileName2 = "azure_new.png"; // Create the source CloudBlob instances CloudBlob sourceBlob1 = Util.GetCloudBlob(ContainerName, sourceBlobName1, BlobType.BlockBlob); CloudBlob sourceBlob2 = Util.GetCloudBlob(ContainerName, sourceBlobName2, BlobType.BlockBlob); // Create a TransferContext shared by both transfers TransferContext sharedTransferContext = new TransferContext(); // Show overwrite prompt in console when OverwriteCallback is triggered sharedTransferContext.OverwriteCallback = (source, destination) => { Console.WriteLine("{0} already exists. Do you want to overwrite it with {1}? (Y/N)", destination, source); while (true) { ConsoleKeyInfo keyInfo = Console.ReadKey(true); char key = keyInfo.KeyChar; if (key == 'y' || key == 'Y') { Console.WriteLine("User choose to overwrite the destination."); return(true); } else if (key == 'n' || key == 'N') { Console.WriteLine("User choose NOT to overwrite the destination."); return(false); } Console.WriteLine("Please press 'y' or 'n'."); } }; // Record the overall progress ProgressRecorder recorder = new ProgressRecorder(); sharedTransferContext.ProgressHandler = recorder; // Start the blob download Task task1 = TransferManager.DownloadAsync(sourceBlob1, destinationFileName1, null /* options */, sharedTransferContext); // Create a DownloadOptions to disable md5 check after data is downloaded. Otherwise, data movement // library will check the md5 checksum stored in the ContentMD5 property of the source CloudFile/CloudBlob // You can uncomment following codes, enable ContentMD5Validation and have a try. // sourceBlob2.Properties.ContentMD5 = "WrongMD5"; // sourceBlob2.SetProperties(); DownloadOptions options = new DownloadOptions(); options.DisableContentMD5Validation = true; // Start the download Task task2 = TransferManager.DownloadAsync(sourceBlob2, destinationFileName2, options, sharedTransferContext); // Wait for both transfers to finish try { await task1; } catch (Exception e) { // Data movement library will throw a TransferException when user choose to not overwrite the existing destination Console.WriteLine(e.Message); } await task2; // Print out the final transfer state Console.WriteLine("Final transfer state: {0}", recorder.ToString()); }