C# azure blob存储与进度条异步下载

C# azure blob存储与进度条异步下载,c#,azure,azure-storage-blobs,C#,Azure,Azure Storage Blobs,我正在尝试使用连接到进度条的.DownloadToStreamAsync()方法获取从Azure Blob存储下载文件的完整示例 我找到了对azure存储sdk旧实现的引用,但它们不使用较新的sdk(实现了这些异步方法)编译,也不使用当前的nuget软件包 我是一个在.NET中使用async/await线程的新手,我想知道是否有人能帮我完成以下内容(在windows窗体应用程序中),并展示我如何“钩住”文件下载过程。。。我看到一些示例没有使用.DownloadToStream方法,而是下载b

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

我找到了对azure存储sdk旧实现的引用,但它们不使用较新的sdk(实现了这些异步方法)编译,也不使用当前的nuget软件包

我是一个在.NET中使用async/await线程的新手,我想知道是否有人能帮我完成以下内容(在windows窗体应用程序中),并展示我如何“钩住”文件下载过程。。。我看到一些示例没有使用.DownloadToStream方法,而是下载blob文件的块。。但我想知道,既然这些新的…Async()方法存在于较新的存储SDK中,是否有更智能的方法可以实现

因此,假设下面的代码正常工作(非异步),我还需要做些什么才能使用blockBlob.DownloadToStreamasync(fileStream);方法,这是正确的使用方法吗?我怎样才能取得进展

理想的情况下,我可以在任何情况下挂接blob下载的进度,以便在大下载时更新Windows窗体UI。。因此,如果下面的方法不正确,请启发我:)


我使用了非常棒的建议(下载1mb块),我已经实现了使用后台工作程序进行下载,这样我就可以在运行时更新UI

do循环中的主要部分将范围下载到流中,然后将流写入我在原始示例中未涉及的文件系统,但我添加了更新工作进程和侦听工作进程取消(中止下载)的代码。。不确定这是否是问题所在

为完整起见,以下是worker\u 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
方法。不久前,我回答了一个类似的问题,您可能会发现这个问题很有用:。

谢谢您的确认。。将使用您建议的块下载示例,并在单独的UI线程上运行,以便我可以从剩余字节等更新进度条。我已经在后台工作程序上实现了这一点,并且所有工作都很好。。几乎。。在一些较大的文件上,进程错误有时会出现在“无法写入另一个进程错误中打开的文件…”上,这可能是向文件系统写入的延迟,或者它试图再次写入?如果不查看您的代码,就无法告诉您为什么会出现错误。你介意分享你的最新代码吗?是的,没问题。。我是新来的。。最好粘贴另一个答案,以便代码可读/语法突出显示,还是我将其张贴在评论中。最可取的方法是更新您的问题并包含您在那里使用的代码。或者,您可以使用pastebin或Github Gist之类的工具,并在注释中共享链接。将此信息放在注释中不是一个好主意:)。嗯。
using (var fileStream = System.IO.File.OpenWrite(@"path\myfile"))
{
    blockBlob.DownloadToStream(fileStream);
}