我可以直接从HttpResponseMessage流式传输到文件而无需通过内存吗?
我的程序使用HttpClient向Web API发送GET请求,并返回一个文件。
我现在使用此代码(简化)将文件存储到光盘:
public async Task DownloadFile() { var client = new HttpClient(); var uri = new Uri("http://somedomain.com/path"); var response = await client.GetAsync(uri); if (response.IsSuccessStatusCode) { var fileName = response.Content.Headers.ContentDisposition.FileName; using (var fs = new FileStream("C:\test\" + fileName, FileMode.Create, FileAccess.Write, FileShare.None)) { await response.Content.CopyToAsync(fs); return true; } } return false; }
现在,当此代码运行时,该进程会将所有文件加载到内存中。 我实际上宁愿期望流从HttpResponseMessage.Content流式传输到FileStream,因此只有一小部分流被保存在内存中。
我们计划在大文件(> 1GB)上使用它,那么有没有办法在没有内存中的所有文件的情况下实现它?
理想情况下,没有手动循环读取一部分到byte []并将该部分写入文件流直到所有内容都被写入?
看起来这是设计 – 如果你查看HttpClient.GetAsync()
的文档,你会看到它说:
读取完整个响应( 包括内容 )后,返回的任务对象将完成
您可以使用HttpClient.GetStreamAsync()
来明确指出:
此方法不缓冲流。
但是,就我所见,您无法访问响应中的标头。 因为这可能是一个要求(当你从头文件中获取文件名时),那么你可能想要使用HttpWebRequest
,它允许你获得响应细节(标题等),而无需将整个响应读入内存。 就像是:
public async Task DownloadFile() { var uri = new Uri("http://somedomain.com/path"); var request = WebRequest.CreateHttp(uri); var response = await request.GetResponseAsync(); ContentDispositionHeaderValue contentDisposition; var fileName = ContentDispositionHeaderValue.TryParse(response.Headers["Content-Disposition"], out contentDisposition) ? contentDisposition.FileName : "noname.dat"; using (var fs = new FileStream(@"C:\test\" + fileName, FileMode.Create, FileAccess.Write, FileShare.None)) { await response.GetResponseStream().CopyToAsync(fs); } return true }
请注意,如果请求返回不成功的响应代码,则会抛出exception,因此您可能希望在try..catch
包装并在此情况下返回false
,如原始示例中所示。
- Web API路由 – 重载的GET方法导致其他动词不允许405方法
- 如何使用ASP.NET Web API在DocumentDB中创建和更新文档之间的关系
- 在ASP Web API中指定无效参数时返回错误
- 使用ASP Identity 2 POST到/ Token端点时始终收到’invalid_client’错误
- 每个appdomain的webapi和未处理的exception挂钩
- DB-First与ASP.NET Web API 2 + EF6的身份validation混淆
- C#Web API POST参数FromBody始终为null
- Web API可选参数
- Web Api 2.2 – 类库项目中的代码优先迁移