hIpPy
hIpPy

Reputation: 5125

Download large csv file (string) chunked or streaming

I want to download a large csv file (100+ mb) through browser but I get timeout. Generating the csv file is time-consuming so I cannot read it all in memory or write to disk first.

public IActionResult Download1()
{
    var bytes = FetchBytes();
    return File(bytes, "text/csv", "download1.csv");
}

FileStreamResult requires pulling all the stream in memory.

// GET or POST
public IActionResult Download()
{
    var stream = FetchStream();
    return new FileStreamResult(stream, "text/csv");
}

I tried writing chunks to response and I can see the file download progress in browser but I do not get the file download or the file download dialog.

// GET or POST
public ActionResult Download()
{
    var response = this.Response;
    var size = 4096;
    foreach (var csvBatch in csvBatches)
    {
        byte[] bytes = Encoding.ASCII.GetBytes(csvBatch);
        using (var ms = new MemoryStream(bytes))
        {
            var data = new byte[size];
            var bytesRead = 0;
            do
            {
                bytesRead = ms.Read(data, 0, size);
                response.Body.Write(data, 0, readBytes);
                response.Body.Flush();
            } while (bytesRead > 0);
        }
    }
    response.ContentType = "text/csv";
    response.Headers.Add("Content-Disposition", $"attachment;filename=\"{fileName}\"");
    // this streams the file but does not download or give file download dialog
}

Net Core does not have the WriteFile(HttpResponseBase) method to override for FileResult as per Writing to Output Stream from Action which can write to Response.OutputStream.

How can I do this?

Upvotes: 1

Views: 3224

Answers (1)

Cinchoo
Cinchoo

Reputation: 6326

There are number of ways you can do it and also there are number of helpful classes available to use. Don't break your head, because they do chunk by default.

The one I would recommend is StreamContent class. It takes buffer size on the constructor.

Here is the sample how it works.

    public async Task<HttpResponseMessage> Download()
    {
        var response = new HttpResponseMessage(HttpStatusCode.OK);

        var stream = await GetStreamFromSomewhereMethod();

        var content = new StreamContent(stream, 4096); //buffer is 4KB

        response.Content = content;
        return response;
    }

Hope it helps.

Upvotes: 2

Related Questions