1

I have a function that returns a Stream with data of a file being downloaded using HttpContent that is the content of a HttpResponseMessage (using Owin)

For those interested I'll add the code at the end.

The interface to get the stream is:

async Task<Stream> DownloadLogFileAsync(...);

The caller of this function wants to create a file containing the data of this Stream. According to StackOverFlow: How do I save a stream to File I should use Stream.CopyTo to save the contents of the Stream in a file. Something like this:

(simplified: not using CancellationToken)

using(Stream downloadStream = await DownloadLogFileAsync(...) )
{
    using (var fileStream = System.IO.File.Create(fullFileName))
    {
        await downloadStream.CopyToAsync(fileStream);
    }
}

Question:
Would it improve performance if the FileStream has the same buffer size as the downloadStream? How do I get the buffer size of the download stream?
End of Question


Not related to the question, only for those interested in the OWIN / ASP file download:

I have a WCF service with a function that returns data. Creation of this data takes a considerable amount of time. The size of the returned data might be huge. Therefore it is decided to split this function into two functions:

  • Request creation of the file. Return a unique file handle
  • Request a stream containing the data of the created file.

Of course my WCF service needs proper functions to cancel creation, delete the created file and do some cleanup if the file is getting old and client forgot to request deletion.

All functions can be done using WCF. The only one that needs OWIN / ASP is the request for the file stream.

class OwinFileClient
{
    private const string routePrefix = "SipLoggerFile/";
    private readonly WebApiClient webApiClient = new WebApiClient() {...}

    // Function to download the created file:
    public async Task<Stream> DownloadSipLogFileAsync(Guid fileHandle)
    {
        var httpClient = this.webApiClient.CreateHttpClient();
        string requestStreamFile = routePrefix + @"DownloadFile?fileHandle="
            + fileHandle.ToString("N");
        var response = await httpClient.GetAsync(requestStreamFile)
            .ConfigureAwait(false);

        if (!response.IsSuccessStatusCode)
        {
            string content = await response
                .Content.ReadAsStringAsync()
                .ConfigureAwait(false);
            throw new System.Net.Http.HttpRequestException(
                $"{response.StatusCode} [{(int)response.StatusCode}]: {content}");
        }

        // if here: success: deserialize the data
        return await response.Content.ReadAsStreamAsync()
            .ConfigureAwait(false);
    }
}

And the WebApiClient:

class WebApiClient
{
    public Uri baseAddress { get; set; }
    public TimeSpan Timeout { get; set; }
    public ICredentials Credentials { get; set; }
    public IWebProxy Proxy { get; set; }

    public HttpClient CreateHttpClient()
    {
        return new HttpClient(CreateHttpMessageHandler())
        {
            BaseAddress = this.baseAddress,
            Timeout = this.Timeout,
        };
    }

    private HttpMessageHandler CreateHttpMessageHandler()
    {
        return new HttpClientHandler()
        {
            AutomaticDecompression = System.Net.DecompressionMethods.GZip
                | System.Net.DecompressionMethods.Deflate,
            Credentials = this.Credentials,
            PreAuthenticate = this.Credentials != null,
            Proxy = this.Proxy,
            UseProxy = this.Proxy != null,
    };
}
Harald Coppoolse
  • 28,834
  • 7
  • 67
  • 116
  • So you have perfomance problem or that's just curiosity? I mean I doubt buffer size will have significant impact. – Evk Mar 02 '18 at 09:35
  • Curiosity. I just want to write perfect code. And of course know what to do next time if I have to copy the data of an readable stream to an writable stream – Harald Coppoolse Mar 02 '18 at 10:51
  • It's not possible to get buffer size in general, unless you know exact type of that `Stream`, and even then you will have to use reflection, because streams do not usually provide this information publically. That said, usual buffer size used by most .NET code is 4kb, so there is high chance your filestream (which has default buffer of 4kb too) has already the same buffer size. How buffer size affects perfomance depends on various factors, cannot be told in general. Side note: you have to provide FileOptions.Asynchronous when creating file, otherwise your writes are not really asynchronous. – Evk Mar 02 '18 at 11:25

0 Answers0