質問

I have to serve large files (200-800MB) to the client from my controller. I tested FileStreamResult, but this class buffered the whole file in memory. This behavior is not good enough for my project.

Further i testest the approach from here: http://support.microsoft.com/kb/812406. Concerning the memory, this looks pretty good -but the files are not completly downloaded on the client (the original file is 210222 KB, the downloaded ones are 209551 to 209776). This means there is about 0.5 MB lost (which concequently causes the files to be broken).

Has somebody an idea? Whats the best way to do this anyway? Im grateful for everything.

Just for users in the future, the link pointed to the following code:

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();
}

Update

This is my action:

    public DownloadResult TransferTest()
    {
        string fullFilePath = @"C:\ws\Test\Test\Templates\example.pdf";
        return new DownloadResult(fullFilePath);
    }

I simply call the action directly from my browser (http://xxx.xxx/Other/TransferTest).

役に立ちましたか?

解決

The code basically looks sound - you are more-or-less correctly handling the return value from Read (if I was being picky, I would say check it for <=0, but this would not be an expected behavior since you probably have a lock on the file).

The only thing that occurs is: try adding a:

Response.OutputStream.Flush();

and perhaps:

Response.OutputStream.Close();

to make sure that the output stream is flushed.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top