我编写了一个 ashx 处理程序,它以安全的方式将文件流式传输到浏览器,我希望用户有权访问这些文件。
问题是,当我蒸大文件(+40 MB)时,会话是goen+浏览器下载在~40 MB后突然中断。
我已将 web.config 配置为在 240 分钟之前不超时。
在本地测试它不会给我同样的问题,在我的共享主机上测试它会。
有人能指出我正确的方向吗?
我尝试过有和没有 Reponse.Clear()
public void ProcessRequest(HttpContext context)
{
int id;
if (new Core.SecurityManager().CurrentUser != null)
{
try
{
id = Convert.ToInt32(context.Request.QueryString["id"]);
}
catch
{
throw new ApplicationException("id could not be parsed.");
}
string filename = new DocumentFactory().SelectDocumentById(id).Filename;
string filePath = context.Server.MapPath("~/uploads/" + filename);
//context.Response.Clear();
context.Response.AddHeader("content-disposition", "attachment; filename=" + filename);
context.Response.ContentType = "application/octet-stream";
context.Response.WriteFile(filePath);
//context.Response.Flush();
//context.Response.End();
}
else
{
throw new AuthenticationException();
}
}
网络配置:
<sessionState mode="InProc" cookieless="false" timeout="240"></sessionState>
编辑尝试以下操作,但下载仍然中断:
FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
byte[] byteArray = new byte[fs.Length];
using (MemoryStream ms = new MemoryStream(byteArray))
{
long dataLengthToRead = ms.Length;
int blockSize = dataLengthToRead >= 5000 ? 5000 : (int)dataLengthToRead;
byte[] buffer = new byte[dataLengthToRead];
context.Response.Clear();
// Clear the content of the response
context.Response.ClearContent();
context.Response.ClearHeaders();
// Buffer response so that page is sent
// after processing is complete.
context.Response.BufferOutput = true;
// Add the file name and attachment,
// which will force the open/cance/save dialog to show, to the header
context.Response.AddHeader("Content-Disposition", "attachment; filename=" + filename);
// bypass the Open/Save/Cancel dialog
//Response.AddHeader("Content-Disposition", "inline; filename=" + doc.FileName);
// Add the file size into the response header
context.Response.AddHeader("Content-Length", fs.Length.ToString());
// Set the ContentType
context.Response.ContentType = "application/octet-stream";
// Write the document into the response
while (dataLengthToRead > 0 && context.Response.IsClientConnected)
{
Int32 lengthRead = ms.Read(buffer, 0, blockSize);
context.Response.OutputStream.Write(buffer, 0, lengthRead);
//Response.Flush();
dataLengthToRead = dataLengthToRead - lengthRead;
}
context.Response.Flush();
context.Response.Close();
}
// End the response
context.Response.End();
当通过浏览器添加完整路径直接进入文件时,下载都没有问题。
尽管在IIS中传递大文件的正确方法是以下选项,
-
在 WebLimits 中将 MinBytesPerSecond 设置为零(这肯定会有助于提高性能,因为 IIS 选择关闭具有较小大小传输的保持 KeepAlive 连接的客户端)
-
将更多工作进程分配给应用程序池,我已设置为 8,现在仅当您的服务器分发较大的文件时才应执行此操作。这肯定会导致其他站点执行速度变慢,但这将确保更好的交付。我们设置为 8,因为该服务器只有一个网站,它只是提供巨大的文件。
-
关闭应用池回收
-
关闭会话
-
保持缓冲开启状态
-
在执行以下每个步骤之前,请检查 Response.IsClientConnected 是否为真,否则放弃并且不要发送任何内容。
-
在发送文件之前设置内容长度
-
刷新响应
-
写入输出流,并定期刷新