2016-10-12 5 views
0

진행률 표시 줄에 연결된 .DownloadToStreamAsync() 메소드를 사용하여 Azure Blob 저장소를 다운로드하는 완전한 예제를 얻으려고합니다.azure blob storage async download with progress bar

하늘색 저장소 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에서, 누군가가 (윈도우 폼 응용 프로그램에서) 아래의 복용과 함께 나를 도울 수 있는지 궁금 보여주는데 어떻게 파일 다운로드 진행에 '연결'할 수 있는지 ... 일부 예제에서는 .DownloadToStream 메서드를 사용하지 말고 대신 BLOB 파일의 청크를 다운로드합니다.하지만이 새로운 이후로 궁금해했습니다 ... Async() 새로운 스토리지 SDK에 방법이 존재할 수 있습니까?

그래서 (비동기가 아닌) 아래의 작업을한다고 가정하면 blockBlob.DownloadToStream을 추가로 사용해야 할 것입니다. 비동기 (fileStream); 방법, 이것이 바로 이것의 올바른 사용법이며, 어떻게 진전을 이룰 수 있습니까?

이상적으로 나는 큰 다운로드에서 Windows Form UI를 업데이트 할 수 있도록 BLOB 다운로드의 진행 상황을 후크 할 수 있습니다. 다음은 올바른 방법이 아닌 경우 나에게 알려주십시오.

친절 Gaurav에 의해 suggsted 멋진 제안 method (다운로드 1메가바이트 덩어리)를 사용하여
// 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 루프의 주요 부분 원래 예제에서는 다루지 않지만 작업자 진행률을 업데이트하고 코드를 수신하는 코드가 추가되었습니다. 작업자 취소 (다운로드 중단). 이것이 문제가 될지 확실하지 않은 경우? 나는 가끔 무엇입니까 '의 오픈 파일에 쓸 수 없습니다

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메가바이트) : 완성도를 들어

, 아래의 worker_DoWork 방법 내부의 모든 것 코드가 t에서 오기 때문에 진행률을 표시 할 수 없습니다

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

: 다른 프로세스 오류 ... '프로세스는 코드를 사용하여 ..

답변

1

실패 그의 기능은 다운로드가 완료되었을 때에 만 가능합니다. DownloadToStream 함수는 큰 블롭을 청크로 내부적으로 분할하고 청크를 다운로드합니다.

코드를 사용하여 이러한 청크를 다운로드하면됩니다. 당신이해야 할 일은 DownloadRangeToStream 방법을 사용하는 것입니다. 나는 비슷한 질문에 답할 시간이 있다고 대답했다 : Azure download blob part.

+0

확인해 주셔서 감사합니다. 블록 예에서 다운로드를 사용하고 UI에 별도의 스레드에서 실행하여 바이트 등의 진행률 막대를 업데이트 할 수 있습니다. –

+0

나는 백그라운드 작업자에게 이것을 구현했고, 그 모든 작업은 멋지게 .. 거의 커다란 파일에서 프로세스 오류가 '다른 프로세스 오류로 열려있는 파일에 쓸 수 없다 ...'라고 할 수있다. 다시 쓰려고하는 파일 시스템에 쓰기가 지연 되니? –

+0

코드를 보지 않고 오류가 발생하는 이유를 알 수 없습니다. 최신 코드를 공유 하시겠습니까? –

관련 문제