I’m working with two API’s which are being used to download large documents from an external system.
I call API 1 with some information about a document to be retrieved, API 1 then calls API 2 with that same information acting as a ‘middleman’. API 1 gets document binary back which it then passes along to the original caller.
What I’d like to avoid is creating large in memory objects representing these documents and just pass a stream as the response all the way through, is this possible with the described setup (‘middleman’ API)?
Basic example of what I have (in 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...
}
The response from this is being read as a stream by the original caller and then passed to a FileStreamResult
which downloads the document on the client machine.
My question(s):
- Is the
var stream = await response.Content.ReadAsStreamAsync()
line still creating a large in memory object representing the document? - Does the above stream need to be disposed or will the underlying
HttpContent
take care of cleaning up the stream? If it does need to be disposed, how can I do this whilst still passing a stream response to the caller? (is that even possible?)
2
Answers
FileStreamResult
reads bytes from an input stream to a buffer (wich is 4kb by default) and writes them to an output stream. So no large in memory object should be created.FileStreamResult
is wrapped inusing
statement. It will be disposed correctly.The
stream
which you are passing toOk
should not be disposed.Ok
will wrap the stream and feed it back as a response to the client, so if you dispose it then the response will fail.Technically speaking, at least according to
IDisposable
mantra, you should disposeresponse
. However, doing so will cause it to dispose the stream also, and therefore you should not disposeresponse
either.Don’t fear that it will cause anything to leak:
HttpResponseMessage
does not dispose anything other than the content stream. See the below source code:You should however dispose
request
with ausing
block, although that also just disposes the content, in your caseparameters
.