使用HTTP客户端从MVC下载文件导致“(System.AggregateException)发生一个或多个错误”

时间:2014-10-15 14:34:29

标签: c# asp.net-mvc xamarin task-parallel-library async-await

我已经将这段代码用于生产很长一段时间了,这个问题才刚刚开始。基本上它是从MVC控制器下载文件。这些文件大约是5到20兆字节。这是一个在iOS上运行的PCL库。用户从服务器下载文件时收到错误。我假设它是暂停,但我不是100%肯定。我们无法在内部重新创建此问题,但我们看到日志中的错误和用户已报告此情况。

我可以在服务器端做些什么来改善这个?客户端没有任何变化,它已成为我们客户群的普遍问题。

服务器代码

    public virtual FileResult BuildDatabaseForSite(Guid organizationId, Guid siteId) {
        var basePath = RESTContext.Config.DBPath;
        var filePath = basePath + @"\" + fileId + ".db";
        byte[] existingDbBytes = null;

        using (new Impersonator(RESTContext.Config.VideoPathUsername, RESTContext.Config.VideoPathDomain,
            RESTContext.Config.VideoPathPassword)) {

            if (System.IO.File.Exists(filePath))
                existingDbBytes = System.IO.File.ReadAllBytes(filePath);
        }                        
        return File(existingDbBytes, "application/octet-stream", "CompassLocal.db");
    }

客户代码

       public void DownloadDatabase(Guid organizationId, Guid siteId) {
            Platform.FileSystem.DeleteFile(Paths.LocalDatabase);
            var url = string.Format("organizations/{0}/Sites/{1}/InitialDatabaseCompressed", organizationId, siteId);
            var webClient = new HttpClient();
            webClient.Timeout = new TimeSpan(0,0,5,0);
            webClient.DefaultRequestHeaders.Add("Authorization", authHeader);
            var stream = webClient.GetStreamAsync(url).Result;
            using (Stream file = File.OpenWrite(Paths.LocalDatabase)) {
                          stream.CopyTo(file);
            }
        }

堆栈跟踪

System.AggregateException: One or more errors occurred
  at System.Threading.Tasks.Task.Wait (Int32 millisecondsTimeout, CancellationToken cancellationToken) [0x00000] in <filename unknown>:0 
  at System.Threading.Tasks.Task.Wait () [0x00000] in <filename unknown>:0 
  at System.Threading.Tasks.Task`1[TResult].get_Result () [0x00000] in <filename unknown>:0 
  at DataFinch.Mobile.Core.Network.RemoteAPI.DownloadDatabase (Guid organizationId, Guid siteId) [0x00000] in <filename unknown>:0 
  at DataFinch.Mobile.Core.Services.Registration.RegistrationService.RegisterDeviceAndDownloadDatabase (System.String username, System.String password, Guid siteId) [0x00000] in <filename unknown>:0 

1 个答案:

答案 0 :(得分:1)

显然这是由超时引起的 - 毕竟,堆栈跟踪指示异常发生在Task.Wait(...) - 这是由任务的Result属性在调用堆栈的内部调用。

因为这发生在客户端,所以在服务器端没有什么可以做的。您可以尝试以某种方式使服务器更快。但我怀疑这会有所帮助,因为移动客户端的可用带宽仍然有限 - 而且还有更多:这取决于每个客户的数据计划。

无论如何,因为您可以(并且您将)始终拥有带宽非常差的客户,因此文件大小通常太大而无法定位移动客户端。您所能做的就是为下一版本的应用程序安排下载逻辑的重构,将您的下载分成更小的块,并使您的客户端代码尽可能地处理这些类型的问题...

此外,在等待如此大的下载时阻塞整个线程,即使它是一个工作线程也是一个坏主意(特别是在没有可用带宽指示的移动客户端上)。这导致线程在很长一段时间内没有响应。你也应该考虑改变这种逻辑。