通过c#下载时,PDF文件已损坏

时间:2017-05-26 22:43:10

标签: c# asp.net .net asp.net-mvc asp.net-core

我有一个REST API,它必须从AWS服务器中的远程URL获取文件。该文件已下载,但当我尝试打开它时,它没有显示任何内容,如损坏。

不会抛出异常

代码就是这个

[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;
            }
        }

1 个答案:

答案 0 :(得分:9)

response.Content.ReadAsStreamAsync().ResultcontentStream.ReadAsync(buffer, 0, buffer.Length).Result是一个等待在您的代码中出现的死锁炸弹。

永远不要在UI代码或服务器代码中等待Task.Result,除非您完全理解这样做的含义。

服务器和UI都使用特殊的SynchronizationContext来调度异步延续回调用线程。当同一个线程已挂起,等待Result时,一切都会锁定。

阅读和摘要:

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

您的CreateTemporaryFile方法应标记为async,您应该await这些来电。

那么,对你的问题。您未在fileStream.WriteAsync(buffer, 0, read)任务完成情况下致电await。在(至少)最后一次写入时,流将在写入完成之前被处理,并具有可预测的结果。

正确使用async 或根本不使用它。那里没有中途宿舍。