将来自 ReadAsStreamAsync 的 Stream 作为 API 响应传递并避免大内存对象
Passing Stream from ReadAsStreamAsync as API response and avoiding large in memory objects
我正在使用两个 API 用于从外部系统下载大型文档。
我调用 API 1 并提供有关要检索的文档的一些信息,API 1 然后调用 API 2 使用与 'middleman' 相同的信息。 API 1 获取文档二进制文件,然后将其传递给原始调用者。
我想避免的是创建表示这些文档的大型内存对象,并一直传递一个流作为响应,这是否可以通过描述的设置实现('middleman' API)?
我所拥有的基本示例(在 API 1 中):
var request = new HttpRequestMessage(HttpMethod.Post, "https://example.com/api/getdocs");
request.Content = parameters;
// 'ResponseHeadersRead' - indicate completion on reading of headers and not entire response...
var response = await httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
if (response.StatusCode == HttpStatusCode.OK)
{
var stream = await response.Content.ReadAsStreamAsync();
return this.Ok(stream);
}
else
{
// Logging/error handling...
}
来自此的响应被原始调用者作为流读取,然后传递给 FileStreamResult
,后者在客户端计算机上下载文档。
我的问题:
var stream = await response.Content.ReadAsStreamAsync()
行是否仍在创建表示文档的大型内存对象?
- 是否需要处理上面的流,或者底层
HttpContent
会负责清理流吗?如果确实需要处理它,我如何在仍然将流响应传递给调用者的同时执行此操作? (这可能吗?)
FileStreamResult
从输入流中读取字节到缓冲区(默认为 4kb)并将它们写入输出流。因此不应创建大内存对象。
FileStreamResult
中的输入流读取过程包含在 using
语句中。它将被正确处理。
您传递给 Ok
的 stream
应该 不 被处理掉。 Ok
将包装流并将其作为响应反馈给客户端,因此如果您处置它,则响应将失败。
从技术上讲,至少根据IDisposable
真言,你应该处置response
。但是,这样做会导致它也处理流,因此您也应该 而不是 处理 response
。
不要担心它会导致任何内容泄漏:HttpResponseMessage
除了内容流之外,不会处理任何内容。见 the below source code:
protected virtual void Dispose(bool disposing)
{
// The reason for this type to implement IDisposable is that it contains instances of types that implement
// IDisposable (content).
if (disposing && !disposed)
{
disposed = true;
if (content != null)
{
content.Dispose();
}
}
}
你 应该 但是用 using
块处理 request
,虽然这也只是处理内容,在你的情况下 parameters
。
我正在使用两个 API 用于从外部系统下载大型文档。
我调用 API 1 并提供有关要检索的文档的一些信息,API 1 然后调用 API 2 使用与 'middleman' 相同的信息。 API 1 获取文档二进制文件,然后将其传递给原始调用者。
我想避免的是创建表示这些文档的大型内存对象,并一直传递一个流作为响应,这是否可以通过描述的设置实现('middleman' API)?
我所拥有的基本示例(在 API 1 中):
var request = new HttpRequestMessage(HttpMethod.Post, "https://example.com/api/getdocs");
request.Content = parameters;
// 'ResponseHeadersRead' - indicate completion on reading of headers and not entire response...
var response = await httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
if (response.StatusCode == HttpStatusCode.OK)
{
var stream = await response.Content.ReadAsStreamAsync();
return this.Ok(stream);
}
else
{
// Logging/error handling...
}
来自此的响应被原始调用者作为流读取,然后传递给 FileStreamResult
,后者在客户端计算机上下载文档。
我的问题:
var stream = await response.Content.ReadAsStreamAsync()
行是否仍在创建表示文档的大型内存对象?- 是否需要处理上面的流,或者底层
HttpContent
会负责清理流吗?如果确实需要处理它,我如何在仍然将流响应传递给调用者的同时执行此操作? (这可能吗?)
FileStreamResult
从输入流中读取字节到缓冲区(默认为 4kb)并将它们写入输出流。因此不应创建大内存对象。FileStreamResult
中的输入流读取过程包含在using
语句中。它将被正确处理。
您传递给 Ok
的 stream
应该 不 被处理掉。 Ok
将包装流并将其作为响应反馈给客户端,因此如果您处置它,则响应将失败。
从技术上讲,至少根据IDisposable
真言,你应该处置response
。但是,这样做会导致它也处理流,因此您也应该 而不是 处理 response
。
不要担心它会导致任何内容泄漏:HttpResponseMessage
除了内容流之外,不会处理任何内容。见 the below source code:
protected virtual void Dispose(bool disposing)
{
// The reason for this type to implement IDisposable is that it contains instances of types that implement
// IDisposable (content).
if (disposing && !disposed)
{
disposed = true;
if (content != null)
{
content.Dispose();
}
}
}
你 应该 但是用 using
块处理 request
,虽然这也只是处理内容,在你的情况下 parameters
。