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?)
CodePudding user response:
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.- Input stream read process in
FileStreamResult
is wrapped inusing
statement. It will be disposed correctly.
CodePudding user response:
The stream
which you are passing to Ok
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 dispose response
. However, doing so will cause it to dispose the stream also, and therefore you should not dispose response
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:
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();
}
}
}
You should however dispose request
with a using
block, although that also just disposes the content, in your case parameters
.