2017-05-26 139 views
0

我有一個REST API,它必須從AWS服務器的遠程URL獲取文件。該文件已下載,但當我嘗試打開它時,它不顯示任何內容,例如損壞。PDF文件在通過c#下載時損壞

沒有異常拋出

的代碼是這樣

[HttpPost] 
     [Route("api/[controller]/UploadFileToAzureStorage")] 
     public async Task<IActionResult> GetFile([FromBody]PDF urlPdf) 
     { 
      string localFilePath = CreateTemporaryFile(urlPdf.urlPDF); 

      // Create storage account 
      CloudStorageAccount storageAccount = CloudStorageAccount.Parse(StorageAccount); 

      // Create a blob client. 
      CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient(); 

      // Get a reference to a container named "mycontainer." 
      CloudBlobContainer container = blobClient.GetContainerReference(UploaderStorage.Container); 

      // Get a reference to a blob named "myblob". 
      CloudBlockBlob blockBlob = container.GetBlockBlobReference("myblob"); 

      // Create or overwrite the "myblob" blob with the contents of a local file 
      // named "myfile". 
      using (var fileStream = System.IO.File.OpenRead(localFilePath)) 
      { 
       await blockBlob.UploadFromStreamAsync(fileStream); 
      } 

      return Ok(); 
     } 


     /// <summary> 
     /// Creates temporary file 
     /// </summary> 
     /// <param name="urlPdf">PDF URL</param> 
     /// <returns>Returns path of the new file</returns> 
     private string CreateTemporaryFile(string urlPdf) 
     { 
      Uri uri = new Uri(urlPdf); 
      string filename = default(string); 
      //if (uri.IsFile) 
      //{ 
       filename = System.IO.Path.GetFileName(uri.LocalPath); 
      //} 

      try 
      { 
       using (var client = new HttpClient()) 
       { 
        using (HttpResponseMessage response = 
         client.GetAsync(urlPdf, HttpCompletionOption.ResponseHeadersRead).Result) 
        { 
         response.EnsureSuccessStatusCode(); 

         using (Stream contentStream = response.Content.ReadAsStreamAsync().Result, fileStream = new FileStream(@"\\pc030\TemporaryPDF\"+ filename, 
          FileMode.Create, FileAccess.Write, FileShare.None, 8192, true)) 
         { 
          var buffer = new byte[8192]; 
          var isMoreToRead = true; 
          do 
          { 
           var read = contentStream.ReadAsync(buffer, 0, buffer.Length).Result; 
           if (read == 0) 
           { 
            isMoreToRead = false; 
           } 
           else 
           { 
            fileStream.WriteAsync(buffer, 0, read); 
           } 
          } 

          while (isMoreToRead); 
         } 
        } 
       } 

       return @"\\pc030\TemporaryPDF\" + filename; 
      } 
      catch(Exception ex) 
      { 
       throw ex; 
      } 
     } 

回答

9

response.Content.ReadAsStreamAsync().ResultcontentStream.ReadAsync(buffer, 0, buffer.Length).Result是死鎖炸彈守候在你的代碼去了。

永遠不要通過在UI代碼或服務器代碼中等待Task.Result來阻止,除非您完全理解這樣做的含義。

服務器和用戶界面都使用特殊SynchronizationContext將異步延續調度回調用線程。當同一個線程已經掛起,等待Result時,一切都會鎖定。

閱讀和消化:

https://blog.stephencleary.com/2012/07/dont-block-on-async-code.html

CreateTemporaryFile方法應標明async,你應該await荷蘭國際集團的電話。

所以,你的問題。您正在調用fileStream.WriteAsync(buffer, 0, read)而沒有await任務完成。在(至少)最後一次寫入時,流將在寫入完成之前丟棄,併產生可預測的結果。

採用async正確或根本就不使用它。沒有中途的房子。