ASP.net在下载过程中的内存使用情况

5
在我工作的ASP.net网站上,以下代码块负责处理文件下载(注意:此处未使用Response.TransmitFile,因为下载内容是从zip文件中流式传输):
private void DownloadFile( Stream stream)
{
        int bytesRead;
        int chunkSize = 1048576; //1MB

        byte[] readBuffer = new byte[chunkSize];
        while ((bytesRead = stream.Read(readBuffer, 0, readBuffer.Length)) != 0)
            {
                if(!Response.IsClientConnected)
                    break;
                byte[] chunk = new byte[bytesRead];
                Array.Copy(readBuffer,0,chunk,0,bytesRead);
                Response.BinaryWrite(chunk);
                Response.Flush();
        }
        stream.Close();
}

我们的用户经常下载几百兆字节的文件,这可能会很快地消耗服务器内存。我的假设是这是由于响应缓冲造成的。这个解释有道理吗?
我刚刚了解到 Response 对象的 'buffer' 属性。如果我将其设置为 false,那么是否可以防止 Response.BinaryWrite() 调用在内存中缓冲数据?一般来说,在这种情况下限制内存使用的好方法是什么?也许我应该从 zip 流式传输到临时文件,然后调用 Response.TransmitFile()?
编辑:除了可能的解决方案,我非常感兴趣的是上述代码中存在的内存使用问题的解释。为什么这会消耗超过1MB,即使在每次循环迭代中都调用了 Response.Flush?这只是在每次循环迭代时发生的不必要的堆分配(并且不会立即得到垃圾回收),还是有其他因素起作用?
1个回答

5
这里有一些我正在处理的代码。它使用一个8000字节的缓冲区来分块发送文件。对于一个大文件的非正式测试表明,内存分配有显著的减少。
int BufferSize = 8000;
FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read);
try {
  long fileSize = stream.Length;

  long dataLeftToRead = fileSize;
  int chunkLength;
  buffer = new Byte[BufferSize];

  while (dataLeftToRead > 0) {
    if (!Response.IsClientConnected) {
      break;
    }
    chunkLength = stream.Read(buffer, 0, BufferSize);

    Response.OutputStream.Write(buffer, 0, chunkLength);
    Response.Flush();

    dataLeftToRead -= chunkLength;
  }
}
finally {
  if (stream != null) {
    stream.Close();
}

已编辑,以修复语法错误和缺失值。

2
使用Response.Write和直接写入Response.OutputStream对象有什么区别? - Odrade
3
Response.Write用于输出字符串或字符,使用流可以发送二进制数据。 - Ray
是的 - 您的循环每次都会分配一个新的缓冲区,这样做是没有必要的。每次循环都会增加1MB的垃圾收集器处理量。WriteFile和TransmitFile似乎都为整个文件分配单个缓冲区,对于大文件来说,这可能会占用大量内存。 - Ray
我对一个大文件(大约3 mb)进行了一些非正式测试。我使用 TransmitFile 观察内存使用情况,发现它跳了3 mb。然后我用我的代码测试,发现没有跳动(8k 要么低于监视器的阈值,要么 .net 已经找到了可用的8k)。 - Ray
@Ray 当前上下文中不存在名称为'buffer'的变量 - pilau
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接