使用HttpClient下载Web api大文件

时间:2014-06-27 12:49:52

标签: winforms asp.net-web-api dotnet-httpclient

我遇到从web api到win forms app的大文件下载问题。在win form app上我使用HttpClient来获取数据。我在服务器端有以下代码:

[HttpPost]
[Route]
public async Task<HttpResponseMessage> GetBackup(BackupRequestModel request)
{
    HttpResponseMessage response;
    try
    {
        response = await Task.Run<HttpResponseMessage>(() =>
        {
            var directory = new DirectoryInfo(request.Path);
            var files = directory.GetFiles();
            var lastCreatedFile = files.OrderByDescending(f => f.CreationTime).FirstOrDefault();
            var filestream = lastCreatedFile.OpenRead();
            var fileResponse = new HttpResponseMessage(HttpStatusCode.OK);
            fileResponse.Content = new StreamContent(filestream);
            fileResponse.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
            return fileResponse;
        });
    }
    catch (Exception e)
    {
        logger.Error(e);
        response = Request.CreateResponse(HttpStatusCode.InternalServerError);
    }
    return response;
}

在客户端:

private async void btnStart_Click(object sender, EventArgs e)
    {
        var requestModel = new BackupRequestModel();
        requestModel.Username = txtUsername.Text;
        requestModel.Password = txtPassword.Text;
        requestModel.Path = txtServerPath.Text;

        var client = new HttpClient();
        var result = await client.PostAsJsonAsync("http://localhost:50116/api/backup", requestModel);
        var stream = await result.Content.ReadAsStreamAsync();
        var localPath = @"d:\test\filenew.bak";
        var fileStream = File.Create(localPath);
        stream.CopyTo(fileStream);
        fileStream.Close();
        stream.Close();
        fileStream.Dispose();
        stream.Dispose();
        client.Dispose();
    }
}

这实际上有效,但此程序的目的是获取超过3GB的大文件并将其保存到客户端。

我已经尝试过这个大小为630MB的文件,我注意到的是:当我用http客户端调用web api时,http客户端实际上在内存流中加载了630MB,从内存流加载到文件流,但是当我尝试加载一个不同的文件我得到OutOfMemoryException。发生这种情况是因为应用程序不会从先前加载的文件中释放内存。我可以在任务管理器中看到它持有635MB的ram内存。

我的问题是如何在不使用内存流的情况下直接将数据从HttpClient写入文件,或者换句话说,当HttpClient下载数据时如何将数据写入文件?

1 个答案:

答案 0 :(得分:1)

要发出请求,请使用SendAsync重载,以便您指定HttpCompletionOption并使用ResponseHeadersRead。您必须手动构建请求,而不使用PostAsJsonAsync便捷方法。