2016-10-12 49 views
0

我想获得一个完整的示例下载文件形式Azure Blob存储使用连接到进度栏.DownloadToStreamAsync()方法。天青blob存储异步下载与进度条

我发现了对azure存储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中的await的线程,并想知道如果有人可以帮助我采取以下(在Windows窗体应用程序),并显示我怎么可以'钩'进入文件下载的进度...我看到一些例子不使用.DownloadToStream方法,他们而是下载blob文件的块..但我想知道,因为这些新... Async()方法存在于较新的Storage SDK中,如果有更聪明的东西可以完成?因此,假设下面的工作(非异步),还需要做什么才能使用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); 
} 

使用真棒建议method(下载1MB块)由Gaurav亲切suggsted,我一直在使用一个后台工作做下载,以便我去哪里,可以更新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为例),我有时我得到“无法写入文件中开放另一个进程的错误......”和过程失败..

回答

1

使用代码:

using (var fileStream = System.IO.File.OpenWrite(@"path\myfile")) 
{ 
    blockBlob.DownloadToStream(fileStream); 
} 

这是不可能的,以显示进度,因为代码出来的T他的功能只有在下载完成时。 DownloadToStream函数将在内部分块大块并下载块。

你需要做的是使用你的代码下载这些块。你需要做的是使用DownloadRangeToStream方法。我回答了一段类似的问题,你可能会觉得有用:Azure download blob part

+0

谢谢您的确认..将使用块中的下载示例,您已经建议并在单独的线程上运行UI,以便我可以从字节左侧等更新进度栏。 –

+0

我已经在后台工作者上实现了这个功能,并且它的所有工作都很好..几乎..在一些更大的文件上,有时会出现进程错误'无法将文件写入另一个进程错误中打开的文件...'当它试图再次写入时,是否延迟写入文件系统? –

+0

不看你的代码,就不可能告诉你为什么会出错。你介意分享你最新的代码吗? –