如何在不使用太多RAM的情况下正确地从MVC3流式传输大数据?

时间:2022-05-14 13:43:33

I'd like to use HttpResponse.OutputStream together with ContentResult so that I can Flush from time to time to avoid using too much RAM by .Net.

我想将HttpResponse.OutputStream与ContentResult一起使用,以便我可以不时刷新以避免使用.Net的太多RAM。

But all examples with MVC FileStreamResult, EmptyResult, FileResult, ActionResult, ContentResult show code that gets all the data into memory and passes to one of those. Also one post suggest that returning EmptyResult together with using HttpResponse.OutputStream is bad idea. How else can I do that in MVC ?

但是MVC FileStreamResult,EmptyResult,FileResult,ActionResult,ContentResult的所有示例都显示了将所有数据存入内存并传递给其中一个的代码。另外一篇文章建议使用HttpResponse.OutputStream返回EmptyResult是个坏主意。我怎么能在MVC中做到这一点?

What is the right way to organize flushable output of big data (html or binary) from MVC server ?

从MVC服务器组织大数据(html或二进制)的可刷新输出的正确方法是什么?

Why is returning EmptyResult or ContentResult or FileStreamResult a bad idea ?

为什么返回EmptyResult或ContentResult或FileStreamResult是个坏主意?

1 个解决方案

#1


5  

You would want to use FileStreamResult if you already had a stream to work with. A lot of times you may only have access to the file, need to build a stream and then output that to the client.

如果您已经有一个要使用的流,您可能希望使用FileStreamResult。很多时候,您可能只能访问该文件,需要构建流然后将其输出到客户端。

System.IO.Stream iStream = null;

// Buffer to read 10K bytes in chunk:
byte[] buffer = new Byte[10000];

// Length of the file:
int length;

// Total bytes to read:
long dataToRead;

// Identify the file to download including its path.
string filepath  = "DownloadFileName";

// Identify the file name.
string  filename  = System.IO.Path.GetFileName(filepath);

try
{
    // Open the file.
    iStream = new System.IO.FileStream(filepath, System.IO.FileMode.Open, 
                System.IO.FileAccess.Read,System.IO.FileShare.Read);


    // Total bytes to read:
    dataToRead = iStream.Length;

    Response.ContentType = "application/octet-stream";
    Response.AddHeader("Content-Disposition", "attachment; filename=" + filename);

    // Read the bytes.
    while (dataToRead > 0)
    {
        // Verify that the client is connected.
        if (Response.IsClientConnected) 
        {
            // Read the data in buffer.
            length = iStream.Read(buffer, 0, 10000);

            // Write the data to the current output stream.
            Response.OutputStream.Write(buffer, 0, length);

            // Flush the data to the HTML output.
            Response.Flush();

            buffer= new Byte[10000];
            dataToRead = dataToRead - length;
        }
        else
        {
            //prevent infinite loop if user disconnects
            dataToRead = -1;
        }
    }
}
catch (Exception ex) 
{
    // Trap the error, if any.
    Response.Write("Error : " + ex.Message);
}
finally
{
    if (iStream != null) 
    {
        //Close the file.
        iStream.Close();
    }
    Response.Close();
}

Here is the microsoft article explaining the above code.

这是解释上述代码的微软文章。

#1


5  

You would want to use FileStreamResult if you already had a stream to work with. A lot of times you may only have access to the file, need to build a stream and then output that to the client.

如果您已经有一个要使用的流,您可能希望使用FileStreamResult。很多时候,您可能只能访问该文件,需要构建流然后将其输出到客户端。

System.IO.Stream iStream = null;

// Buffer to read 10K bytes in chunk:
byte[] buffer = new Byte[10000];

// Length of the file:
int length;

// Total bytes to read:
long dataToRead;

// Identify the file to download including its path.
string filepath  = "DownloadFileName";

// Identify the file name.
string  filename  = System.IO.Path.GetFileName(filepath);

try
{
    // Open the file.
    iStream = new System.IO.FileStream(filepath, System.IO.FileMode.Open, 
                System.IO.FileAccess.Read,System.IO.FileShare.Read);


    // Total bytes to read:
    dataToRead = iStream.Length;

    Response.ContentType = "application/octet-stream";
    Response.AddHeader("Content-Disposition", "attachment; filename=" + filename);

    // Read the bytes.
    while (dataToRead > 0)
    {
        // Verify that the client is connected.
        if (Response.IsClientConnected) 
        {
            // Read the data in buffer.
            length = iStream.Read(buffer, 0, 10000);

            // Write the data to the current output stream.
            Response.OutputStream.Write(buffer, 0, length);

            // Flush the data to the HTML output.
            Response.Flush();

            buffer= new Byte[10000];
            dataToRead = dataToRead - length;
        }
        else
        {
            //prevent infinite loop if user disconnects
            dataToRead = -1;
        }
    }
}
catch (Exception ex) 
{
    // Trap the error, if any.
    Response.Write("Error : " + ex.Message);
}
finally
{
    if (iStream != null) 
    {
        //Close the file.
        iStream.Close();
    }
    Response.Close();
}

Here is the microsoft article explaining the above code.

这是解释上述代码的微软文章。