2
votes

I have a problem with large file download from the web api to the win forms app. On the win form app I'm using HttpClient for grabbing data. I have following code on server side:

[HttpPost]
[Route]
public async Task<HttpResponseMessage> GetBackup(BackupRequestModel request)
{
    HttpResponseMessage response;
    try
    {
        response = await Task.Run<HttpResponseMessage>(() =>
        {
            var directory = new DirectoryInfo(request.Path);
            var files = directory.GetFiles();
            var lastCreatedFile = files.OrderByDescending(f => f.CreationTime).FirstOrDefault();
            var filestream = lastCreatedFile.OpenRead();
            var fileResponse = new HttpResponseMessage(HttpStatusCode.OK);
            fileResponse.Content = new StreamContent(filestream);
            fileResponse.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
            return fileResponse;
        });
    }
    catch (Exception e)
    {
        logger.Error(e);
        response = Request.CreateResponse(HttpStatusCode.InternalServerError);
    }
    return response;
}

on client side:

private async void btnStart_Click(object sender, EventArgs e)
    {
        var requestModel = new BackupRequestModel();
        requestModel.Username = txtUsername.Text;
        requestModel.Password = txtPassword.Text;
        requestModel.Path = txtServerPath.Text;

        var client = new HttpClient();
        var result = await client.PostAsJsonAsync("http://localhost:50116/api/backup", requestModel);
        var stream = await result.Content.ReadAsStreamAsync();
        var localPath = @"d:\test\filenew.bak";
        var fileStream = File.Create(localPath);
        stream.CopyTo(fileStream);
        fileStream.Close();
        stream.Close();
        fileStream.Dispose();
        stream.Dispose();
        client.Dispose();
    }
}

This is actually working, but the purpose of this program is to grab large files over 3GB and save it to the client.

I have tried this on files sized 630MB what I notice is: When I call web api with http client, http client actually loads 630MB in the memory stream, and from the memory stream to the file stream, but when I try to load a different file I'm getting OutOfMemoryException. This is happening because the application doesn't release memory from the previous loaded file. I can see in task manager that it is holding 635MB of ram memory.

My question is how can I write data directly from HttpClient to file without using memory stream, or in other words how can I write data to file while HttpClient is downloading data?

1
You mention winforms by you've tagged this asp.net?Jeff B
Sorry, I have fixed this, I think tags are now better.paradoxx.net

1 Answers

4
votes

To make the request, use a SendAsync overload that allows you to specify a HttpCompletionOption and use ResponseHeadersRead. You'll have to manually build the request though, without using the PostAsJsonAsync convenience method.