C#以更少的内存消耗从服务器下载大文件

标签 c# asp.net-mvc stream filestream

我有一个内存大小为 42 MB 的大文件。我想下载内存占用少的文件。
Controller 代码

public ActionResult Download()
{
    var filePath = "file path in server";
    FileInfo file = new FileInfo(filePath);
    Response.ContentType = "application/zip";                        
    Response.AppendHeader("Content-Disposition", "attachment; filename=folder.zip");                   
    Response.TransmitFile(file.FullName);
    Response.End(); 
}

尝试使用 Stream
的替代方法

public ActionResult Download()
{           
    string failure = string.Empty;
    Stream stream = null;
    int bytesToRead = 10000;


    long LengthToRead;
    try
    {
        var path = "file path from server";
        FileWebRequest fileRequest = (FileWebRequest)FileWebRequest.Create(path);
        FileWebResponse fileResponse = (FileWebResponse)fileRequest.GetResponse();

        if (fileRequest.ContentLength > 0)
            fileResponse.ContentLength = fileRequest.ContentLength;

        //Get the Stream returned from the response
        stream = fileResponse.GetResponseStream();

        LengthToRead = stream.Length;

        //Indicate the type of data being sent
        Response.ContentType = "application/octet-stream";

        //Name the file 
        Response.AddHeader("Content-Disposition", "attachment; filename=SolutionWizardDesktopClient.zip");
        Response.AddHeader("Content-Length", fileResponse.ContentLength.ToString());

        int length;
        do
        {
            // Verify that the client is connected.
            if (Response.IsClientConnected)
            {
                byte[] buffer = new Byte[bytesToRead];

                // Read data into the buffer.
                length = stream.Read(buffer, 0, bytesToRead);

                // and write it out to the response's output stream
                Response.OutputStream.Write(buffer, 0, length);

                // Flush the data
                Response.Flush();

                //Clear the buffer
                LengthToRead = LengthToRead - length;
            }
            else
            {
                // cancel the download if client has disconnected
                LengthToRead = -1;
            }
        } while (LengthToRead > 0); //Repeat until no data is read

    }
    finally
    {
        if (stream != null)
        {
            //Close the input stream                   
            stream.Close();
        }
        Response.End();
        Response.Close();
    }
    return View("Failed");
}

由于文件的大小,它会消耗更多的内存,从而导致性能问题。
检查 iis 日志后,下载过程分别占用 42 MB 和 64 MB。
提前致谢

最佳答案

更好的选择是使用 FileResult 而不是 ActionResult:

使用此方法意味着您不必在服务前将文件/字节加载到内存中。

public FileResult Download()
{
     var filePath = "file path in server";
     return new FilePathResult(Server.MapPath(filePath), "application/zip");
}

编辑:对于较大的文件,FilePathResult 也会失败。

您最好的选择可能是 Response.TransmitFile()然后。我已经在较大的文件 (GB) 上使用过它并且之前没有任何问题

public ActionResult Download()
{
   var filePath = @"file path from server";

    Response.Clear();
    Response.ContentType = "application/octet-stream";
    Response.AppendHeader("Content-Disposition", "filename=" + filePath);

    Response.TransmitFile(filePath);

    Response.End();

    return Index();
}

来自 MSDN:

Writes the specified file directly to an HTTP response output stream, without buffering it in memory.

关于C#以更少的内存消耗从服务器下载大文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43804446/

相关文章:

asp.net - 数百个 ASP.NET MVC 路由

c++ - c++中使用getline()时如何判断是否是EOF?

c# - BinaryReader.Dispose(bool disposing) 创建流的本地引用。为什么?

带流的 WCF Rest Web 服务

c# - HttpClient : Conditionally set AcceptEncoding compression at runtime

c# - 获取字段的默认值

c# - .NET Core 中是否弃用了 ApiController

c# - 为什么 Visual Studio 无法在这个简单的 C# 属性上设置条件断点?

c# - Xamarin Resource.Designer.cs 生成 const 而不是 static

asp.net-mvc - FilePond如何将删除的文件的名称或id作为参数传递给 Controller ​​?