gpt4 book ai didi

c# - 带进度条的 Azure Blob 存储异步下载

转载 作者:太空宇宙 更新时间:2023-11-03 12:38:32 26 4
gpt4 key购买 nike

我正在尝试获取使用连接到进度栏的 .DownloadToStreamAsync() 方法从 Azure Blob 存储下载文件的完整示例。

我发现了对 azure storage sdk 的旧实现的引用,但它们不能使用较新的 sdk(已实现这些异步方法)进行编译,也不能与当前的 nuget 包一起使用。

https://blogs.msdn.microsoft.com/avkashchauhan/2010/11/03/uploading-a-blob-to-azure-storage-with-progress-bar-and-variable-upload-block-size/

https://blogs.msdn.microsoft.com/kwill/2013/03/05/asynchronous-parallel-blob-transfers-with-progress-change-notification-2-0/

我是 .NET 中异步/等待线程的新手,想知道是否有人可以帮助我完成以下内容(在 Windows 窗体应用程序中)并展示我如何“ Hook ”到该进程的进度文件下载...我看到一些示例不使用 .DownloadToStream 方法,而是下载 blob 文件的 block ..但我想知道,因为这些新的 ...Async() 方法存在于较新的存储 SDK 中,如果有的话可以做一些更聪明的事情吗?

因此,假设以下内容正常工作(非异步),我还需要做什么才能使用 blockBlob.DownloadToStreamAsync(fileStream);方法,这是否是正确的使用方法,我怎样才能获得进度?

理想情况下,我想通过任何方式来 Hook 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);
}
<小时/>

使用很棒的建议 method (下载 1mb block )Gaurav 的建议,我已经实现了使用后台 worker 来进行下载,这样我就可以随时更新 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 分割成多个 block 并下载这些 block 。

您需要做的是使用您的代码下载这些 block 。您所要做的就是使用 DownloadRangeToStream 方法。我不久前回答了一个类似的问题,您可能会觉得有用:Azure download blob part .

关于c# - 带进度条的 Azure Blob 存储异步下载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39990239/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com