ASP.NET MVC: Returning large amounts of data from

2019-04-25 13:57发布

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?

3条回答
爷的心禁止访问
2楼-- · 2019-04-25 14:26

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

查看更多
我只想做你的唯一
3楼-- · 2019-04-25 14:29

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.

查看更多
Animai°情兽
4楼-- · 2019-04-25 14:43

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

Response.BufferOutput = false;
return File(fileStream, contentType);
查看更多
登录 后发表回答