下载期间 ASP.net 内存使用情况

发布于 2024-08-19 02:00:13 字数 1047 浏览 5 评论 0原文

在我工作地点的 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();
}

我们的用户经常下载数百MB的文件,这会很快消耗服务器内存。我的假设是这是由于响应缓冲造成的。这有道理吗?

我刚刚读到了 Response 对象的“buffer”属性。如果我将其设置为 false,是否会阻止 Response.BinaryWrite() 调用在内存中缓冲数据?一般来说,在这种情况下限制内存使用的好方法是什么?也许我应该从 zip 流式传输到临时文件,然后调用 Response.TransmitFile()?

编辑:除了可能的解决方案之外,我对上面代码中存在的内存使用问题的解释非常感兴趣。即使每次循环迭代都会调用 Response.Flush,为什么这会消耗远远超过 1MB 的空间?是否只是每次循环迭代时发生不必要的堆分配(并且不会立即进行 GC),还是还有其他原因在起作用?

On an ASP.net site at my place of work, the following chunk of code is responsible for handling file downloads (NOTE: Response.TransmitFile is not used here because the contents of the download are being streamed from a zip file):

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

Our users frequently download multi-hundred MB files, which can chew up server memory pretty fast. My assumption is that this is due to response buffering. Does that make sense?

I've just read about the 'buffer' property of the Response object. If I set that to false, will that prevent the Response.BinaryWrite() calls from buffering the data in memory? In general, what is a good way to limit memory usage in this situation? Perhaps I should stream from the zip to a temporary file, then call Response.TransmitFile()?

EDIT: In addition to possible solutions, I'm very interested in explanations of the memory usage issue present in the code above. Why would this consume far more than 1MB, even though Response.Flush is called on every loop iteration? Is it just the unnecessary heap allocation that occurs on every loop iteration (and doesn't get GC'd right away), or is there something else at work?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

腹黑女流氓 2024-08-26 02:00:13

这是我正在为此编写的一些代码。它使用 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();
}

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

Here is some code that I am working on for this. It uses an 8000 byte buffer to send the file in chunks. Some informal testing on a large file showed a significant decrease in memory allocated.

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

edited to fix a syntax error and a missing value

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文