ASP.NET MVC: Returning large amounts of data from FileResult

I have a file browser application in MVC4 that allows you to download a selected file from a controller.

Currently, the FileResult returns the Stream of the file, along with the other response headers. While this works fine for smaller files, files that are larger generate an OutOfMemoryException.

What I’d like to do is transmit the file from the controller, without buffering in memory in a fashion similiar to HttpReponse.TransmitFile in WebForms.

How can this be accomplished?

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

You can disable the response buffer before you return the file result.

Response.BufferOutput = false;
return File(fileStream, contentType);

Method 2

Yes you can by using Web Api in order to stream the file, take a look at this article Dealing with large files in ASP.NET Web API

Method 3

Additionaly to the above link describing configuration, you may use TransmitFile to “stream” files. However, TransmitFile has some backwards on some http clients.

This is my code to “stream” files to client, as an alternative for TransmitFile. Note that I’ve have a config constant to rollback with WriteFile (which have the same OutOfMemory issue as yours) :

    private void RenderContent(string contentType,string fileName, bool inline);

method code :
FileInfo fi = new FileInfo(fileName);

Response.ClearHeaders();
Response.ClearContent();

Response.ContentType = contentType;
Response.CacheControl = "No-cache";
Response.Cache.SetCacheability(System.Web.HttpCacheability.NoCache);
Response.AddHeader("Content-Length", fi.Length.ToString());
Response.AddHeader("Content-Disposition", (inline ? "inline" : "attachment") + "; filename="" + fi.Name + """);

if (cAppInfos.Constant["FallBackToWriteFile"] != null && cAppInfos.Constant["FallBackToWriteFile"] == "true")
{
    Response.WriteFile(fileName);
}
else
{
    int chunkSize = 8192;
    byte[] buffer = new byte[chunkSize];
    int offset = 0;
    int read = 0;
    using (FileStream fs = File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
    {
        while ((read = fs.Read(buffer, offset, chunkSize)) > 0)
        {
            if (!Response.IsClientConnected)
                break;

            Response.OutputStream.Write(buffer, 0, read);
            Response.Flush();
        }
    }
}

I used this code to avoid some problems in streaming pdf files to old acrobat reader plugin. For the inline parameter, you may use “false”.

Additionaly, you may use try/catch around this code, as any of Response.IsClientConnecter/Write/Flush can throw exceptions if client disconnect.

However, I’m not using MVC, and I’m not sure this is acceptable for this techno, as if you have not used TransmitFile, you may be stuck with the same issue with this code.
If you are trying to embedd files into web pages element (as base64 maybe ?) this is not the solution.

Let me know more information about your requirements, if you need others ways to achieve your goals.


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x