[英]azure blob storage async download with progress bar
我正在嘗試使用連接到進度條的 .DownloadToStreamAsync() 方法從 Azure Blob 存儲下載文件的完整示例。
我發現了對 azure 存儲 sdk 舊實現的引用,但它們不能與較新的 sdk(已實現這些異步方法)一起編譯,或者不能與當前的 nuget 包一起使用。
我是 .NET 中異步/等待線程的新手,想知道是否有人可以幫助我解決以下問題(在 Windows 窗體應用程序中)並展示我如何“掛鈎”文件下載的進度。 .. 我看到一些示例不使用 .DownloadToStream 方法,而是下載 blob 文件的塊。可以做嗎?
因此,假設以下工作正常(非異步),我還需要做什么才能使用 blockBlob.DownloadToStream Async (fileStream); 方法,這甚至是正確的使用方法,我怎樣才能取得進展?
理想情況下,我想通過任何方式我可以掛鈎 blob 下載的進度,以便我可以在大下載時更新 Windows 窗體 UI..所以如果下面的方法不正確,請賜教:)
// Retrieve storage account from connection string.
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(
CloudConfigurationManager.GetSetting("StorageConnectionString"));
// Create the blob client.
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
// Retrieve reference to a previously created container.
CloudBlobContainer container = blobClient.GetContainerReference("mycontainer");
// Retrieve reference to a blob named "photo1.jpg".
CloudBlockBlob blockBlob = container.GetBlockBlobReference("photo1.jpg");
// Save blob contents to a file.
using (var fileStream = System.IO.File.OpenWrite(@"path\myfile"))
{
blockBlob.DownloadToStream(fileStream);
}
使用Gaurav建議的很棒的建議方法(下載 1mb 塊),我已經使用后台工作人員進行下載,這樣我就可以隨時更新 UI。
do 循環中的主要部分將范圍下載到流,然后將流寫入我沒有從原始示例中觸及的文件系統,但我添加了代碼來更新工作進程並偵聽工作取消(以中止下載).. 不確定這是否可能是問題?
為了完整起見,以下是 worker_DoWork 方法中的所有內容:
public void worker_DoWork(object sender, DoWorkEventArgs e)
{
object[] parameters = e.Argument as object[];
string localFile = (string)parameters[0];
string blobName = (string)parameters[1];
string blobContainerName = (string)parameters[2];
CloudBlobClient client = (CloudBlobClient)parameters[3];
try
{
int segmentSize = 1 * 1024 * 1024; //1 MB chunk
var blobContainer = client.GetContainerReference(blobContainerName);
var blob = blobContainer.GetBlockBlobReference(blobName);
blob.FetchAttributes();
blobLengthRemaining = blob.Properties.Length;
blobLength = blob.Properties.Length;
long startPosition = 0;
do
{
long blockSize = Math.Min(segmentSize, blobLengthRemaining);
byte[] blobContents = new byte[blockSize];
using (MemoryStream ms = new MemoryStream())
{
blob.DownloadRangeToStream(ms, startPosition, blockSize);
ms.Position = 0;
ms.Read(blobContents, 0, blobContents.Length);
using (FileStream fs = new FileStream(localFile, FileMode.OpenOrCreate))
{
fs.Position = startPosition;
fs.Write(blobContents, 0, blobContents.Length);
}
}
startPosition += blockSize;
blobLengthRemaining -= blockSize;
if (blobLength > 0)
{
decimal totalSize = Convert.ToDecimal(blobLength);
decimal downloaded = totalSize - Convert.ToDecimal(blobLengthRemaining);
decimal blobPercent = (downloaded / totalSize) * 100;
worker.ReportProgress(Convert.ToInt32(blobPercent));
}
if (worker.CancellationPending)
{
e.Cancel = true;
blobDownloadCancelled = true;
return;
}
}
while (blobLengthRemaining > 0);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
這是有效的,但在更大的文件(例如 30mb)上,我有時會收到“無法寫入文件,因為在另一個進程錯誤中打開......”並且進程失敗..
使用您的代碼:
using (var fileStream = System.IO.File.OpenWrite(@"path\myfile"))
{
blockBlob.DownloadToStream(fileStream);
}
無法顯示進度,因為只有在下載完成時,代碼才會從該函數中出來。 DownloadToStream
函數將在內部將大 blob 分成塊並下載這些塊。
您需要做的是使用您的代碼下載這些塊。 您需要做的是使用DownloadRangeToStream
方法。 前段時間我回答了一個類似的問題,您可能會發現它很有用: Azure 下載 blob 部分。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.