2016-10-12 25 views
0

プログレスバーに接続された.DownloadToStreamAsync()メソッドを使用してAzure Blobストレージをダウンロードする完全な例を取得しようとしています。azure blob storage async download with progress bar

azureストレージsdkの古い実装への参照が見つかりましたが、これらの非同期メソッドを実装した新しいsdkでコンパイルしたり、現在のnugetパッケージでは動作しません。

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

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

は私が初心者だと非同期/のawaitスレッド.NETで、と誰かが(Windowsフォームアプリで)以下の服用で私を助けることができれば不思議と見せていましたどのように私は 'ファイルの進行状況にフック'することができます...私はいくつかの例を参照してください.DownloadToStreamメソッドを使用しないで、代わりにBLOBファイルのチャンクをダウンロード..しかし、私はこれらの新しい... Async()よりスマートな方法があれば、新しいStorage SDKのメソッドが存在するのでしょうか?

したがって、以下が非同期で動作していると仮定すると、blockBlob.DownloadToStreamを使用するためにさらに必要なことは何ですか?非同期(fileStream);方法は、これもこれの右の使用ですか、私はどのように進歩を得ることができますか?

理想的には私はちょうどblobのダウンロードの進捗状況をフックできるので、大きなダウンロードでWindowsフォームUIを更新することができます。以下は正しい方法でない場合は私に教えてください:)

親切 Gauravによってsuggsted素晴らしい提案 method(ダウンロード1MBのチャンク)を使用して
// 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); 
} 

は、私が行くように、私は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); 
     } 
    } 

これが動作しているが、大きなファイル(例えば30メガバイト)の上に、私は時々「のように開いているファイルに書き込むことはできません取得していますコードはトンから出てくるので、進行状況を表示することはできません

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

:別のプロセスエラー...」とプロセスがあなたのコードを使用して...

答えて

1

失敗します彼の機能はダウンロードが完了したときだけです。 DownloadToStream関数は内部的に大きなブロブをチャンクで分割し、チャンクをダウンロードします。

コードでこれらのチャンクをダウンロードするだけです。あなたがしなければならないのは、DownloadRangeToStreamメソッドを使うことです。私はあなたが役に立つと思うかもしれない似たような質問に答えました:Azure download blob part

+0

確認していただきありがとうございます。あなたが示唆しているブロックの例でダウンロードを使用し、UIへの別のスレッドで実行するので、残りのバイトからプログレスバーを更新することができます。 –

+0

私はこれをバックグラウンドワーカーに実装しました。そのすべてがうまくいきました。いくつかの大きなファイルでは、プロセスエラーが「別のプロセスエラーで開いているファイルに書き込めません...」もう一度書き込もうとすると、ファイルシステムへの書き出しが遅れますか? –

+0

あなたのコードを見ることなく、なぜエラーが出ているのかを知ることはできません。最新のコードを共有してもよろしいですか? –

関連する問題