在我工作地点的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()?
编辑:除了可能的解决方案之外,我对上面代码中存在的内存使用问题的解释非常感兴趣。为什么这会消耗远远超过1MB,即使在每次循环迭代时调用Response.Flush?它只是在每次循环迭代时发生的不必要的堆分配(并且不会立即得到GC),或者还有其他工作吗?
答案 0 :(得分:4)
以下是我正在为此工作的一些代码。它使用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();
}
编辑以修复语法错误和缺失值