用Response.OutputStream.Write点【取消】按钮导致IIS崩溃,重金悬赏解决方案

wdf618 2011-08-02 04:09:36


using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.IO;

public partial class Default2 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{

}
protected void Button1_Click(object sender, EventArgs e)
{
string baseFolder = System.Web.HttpContext.Current.Server.MapPath(".");
baseFolder += "\\wdt_m21\\Files_in\\lhpy\\";
string fn = "LHPY_0659H4FCRW2011_05_06_19_26_589UCIV040C5_271719373042.pdf";
FileDownload(baseFolder, fn, "", "");
}

public static void FileDownload(string FilePath, string FileName, string FileType, string FileTitle)
{
string strFullFileName = FilePath + FileName;

long chunkSize = 102400; //建立一个100K的缓冲区
byte[] buffer = new byte[chunkSize];
long dataToRead = 0;//已读的字节数
FileStream stream = null;


stream = new FileStream(strFullFileName, FileMode.Open, FileAccess.Read, FileShare.Read);
dataToRead = stream.Length;

HttpContext.Current.Response.Clear();
HttpContext.Current.Response.ClearHeaders();
HttpContext.Current.Response.Buffer = false;

if (FileType == "")
{
FileType = FileName.Substring(FileName.LastIndexOf(".") + 1);
}
switch (FileType.ToString().ToUpper())
{
case "XLS":
HttpContext.Current.Response.ContentType = "application/ms-excel";
break;
case "DOC":
HttpContext.Current.Response.ContentType = "application/ms-word";
break;
case "TXT":
HttpContext.Current.Response.ContentType = "application/text";
break;
case "PDF":
HttpContext.Current.Response.ContentType = "application/pdf";
break;
case "GIF":
HttpContext.Current.Response.ContentType = "images/gif";
break;
case "JPG":
HttpContext.Current.Response.ContentType = "images/jpg";
break;
}
HttpContext.Current.Response.AppendHeader("Content-Disposition", "attachment;filename=" + HttpUtility.UrlEncode(FileName, System.Text.Encoding.UTF8));
HttpContext.Current.Response.AddHeader("Content-Length", dataToRead.ToString());

while (dataToRead > 0)
{
if (HttpContext.Current.Response.IsClientConnected)
{
int length = stream.Read(buffer, 0, Convert.ToInt32(chunkSize));
HttpContext.Current.Response.OutputStream.Write(buffer, 0, length);
//HttpContext.Current.Response.End();
HttpContext.Current.Response.Flush();
HttpContext.Current.Response.Clear();
dataToRead -= length;
}
else
{
dataToRead = -1; //防止client失去连接
}
}

//HttpContext.Current.Response.End();




}
}




以上代码为利用缓冲区提供文件下载的代码,运行Button1_Click后会蹦出文件下载对话框,如果点【打开】或者【保存】都没问题,文件可以高效的下载完成,但是如果点【取消】,IIS就会崩溃。有时候点取消后需要等几秒钟,这几秒钟内网站还可以有响应,但是随即就崩溃了。

请各位修改上述代码以解决该问题
...全文
614 43 打赏 收藏 转发到动态 举报
写回复
用AI写文章
43 条回复
切换为时间正序
请发表友善的回复…
发表回复
heriver 2012-07-17
  • 打赏
  • 举报
回复
[Quote=引用 41 楼 的回复:]

同样的问题,折腾了两天;用这个没问题:
C# code
Response.Clear();
Response.ClearContent();
Response.ClearHeaders();
Respo……
[/Quote]

膜拜
zrdzxh 2011-12-07
  • 打赏
  • 举报
回复
丢了两句:
                    string newFileName = 新文件名;
string downUrl = Server.MapPath(虚拟路径);

FileInfo downFile = new FileInfo(downUrl);
zrdzxh 2011-12-07
  • 打赏
  • 举报
回复
同样的问题,折腾了两天;用这个没问题:
                        Response.Clear();
Response.ClearContent();
Response.ClearHeaders();
Response.AddHeader("Content-Disposition", "attachment;filename=" + HttpUtility.UrlEncode(newFileName));
Response.AddHeader("Content-Length", downFile.Length.ToString());
Response.AddHeader("Content-Transfer-Encoding", "binary");
Response.ContentType = "application/octet-stream";
Response.ContentEncoding = System.Text.Encoding.GetEncoding("gb2312");
Response.WriteFile(downFile.FullName);
Response.Flush();
Response.End();
  • 打赏
  • 举报
回复
如果要下载的文件比较大,客户点了下载之后,马上把下载的对话框关掉,你那个程序也会进入
while (dataToRead > 0){.. dataToRead = -1;}中导致IIS工作进程崩溃
改一下吧


//这里,唯一让服务器持续输出数据的理由只有两个:当前下载请求仍然没有中断,且数据没有输出完毕
while (HttpContext.Current.Response.IsClientConnected && dataToRead > 0)
{
int length = stream.Read(buffer, 0, Convert.ToInt32(chunkSize));
HttpContext.Current.Response.OutputStream.Write(buffer, 0, length);
//HttpContext.Current.Response.End();
HttpContext.Current.Response.Flush();
HttpContext.Current.Response.Clear();
dataToRead -= length;
}
}

实际上只要HttpContext.Current.Response.IsClientConnected=false了,就应该马上Response.End
xuexiaodong2009 2011-08-03
  • 打赏
  • 举报
回复
解决不了,还不向上放映?出了事,还不成替罪羊了?
xuexiaodong2009 2011-08-03
  • 打赏
  • 举报
回复
[Quote=引用 36 楼 wdf618 的回复:]

引用 35 楼 xuexiaodong2009 的回复:
还是别用while循环下载文件了,能快多少啊?
那个保存取消是浏览器弹出的框,能处理吗?

我一直有的这种方式没有出过错
Response.ClearContent();
Response.ContentType = "image/jpeg";
Response.BinaryWrite(GeneralMethods.File……
[/Quote]那就把问题告诉他,看他怎么解决IIS死的问题
wdf618 2011-08-03
  • 打赏
  • 举报
回复
[Quote=引用 35 楼 xuexiaodong2009 的回复:]
还是别用while循环下载文件了,能快多少啊?
那个保存取消是浏览器弹出的框,能处理吗?

我一直有的这种方式没有出过错
Response.ClearContent();
Response.ContentType = "image/jpeg";
Response.BinaryWrite(GeneralMethods.FileToByteArray(Server.MapPath(……
[/Quote]

用这方法不是我决定的,我也是干事的人....按我的想法,小文件直接给个链接大文件FTP就行了
xuexiaodong2009 2011-08-03
  • 打赏
  • 举报
回复
还是别用while循环下载文件了,能快多少啊?
那个保存取消是浏览器弹出的框,能处理吗?

我一直有的这种方式没有出过错
Response.ClearContent();
Response.ContentType = "image/jpeg";
Response.BinaryWrite(GeneralMethods.FileToByteArray(Server.MapPath(Utilities.DefaultLogoPath)));
Response.End();
wdf618 2011-08-03
  • 打赏
  • 举报
回复
[Quote=引用 33 楼 dongxinxi 的回复:]
你不说点取消后也依然会进入FileDownload方法吗?关键在这里,你的取消事件代码?
[/Quote]
怎么能取消呢?
  • 打赏
  • 举报
回复
你不说点取消后也依然会进入FileDownload方法吗?关键在这里,你的取消事件代码?
wdf618 2011-08-03
  • 打赏
  • 举报
回复
[Quote=引用 31 楼 dongxinxi 的回复:]
如果要下载的文件比较大,客户点了下载之后,马上把下载的对话框关掉,你那个程序也会进入
while (dataToRead > 0){.. dataToRead = -1;}中导致IIS工作进程崩溃
改一下吧


C# code


//这里,唯一让服务器持续输出数据的理由只有两个:当前下载请求仍然没有中断,且数据没有输出完毕
while (HttpContext.Current.……
[/Quote]

这样改了问题依旧存在,并未改善。
实际上点了取消之后while循环即终止,不会死循环,因为else中把dataToRead设为了-1,因此循环终止了
wdf618 2011-08-03
  • 打赏
  • 举报
回复
[Quote=引用 38 楼 xuexiaodong2009 的回复:]
解决不了,还不向上放映?出了事,还不成替罪羊了?
[/Quote]
已经反映了
  • 打赏
  • 举报
回复
要知道你在看某个网页的时候,但你的那个请求早都已经和服务器断开了(这里不说长连接)就算你断网了它也还在那儿,直到你刷新,你才知道断网了不是吗?

弹提示框那里改一下,自己在网页上做一个吧,JQuery的也很多,直到用户确认下载了,服务端才应该开始去读数据并Response,否则,你都不应该告诉服务器客户端有人取消了某个下载(它会忙死的)
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 wdf618 的回复:]
引用 2 楼 xuexiaodong2009 的回复:
取消是不是也进FileDownload(string FilePath, string FileName, string FileType, string FileTitle)里边了?

是啊,不进去怎么能弹出下载框呢?
[/Quote]

逻辑问题,点取消为什么还要进去那个方法?点取消就是客户端关闭下载对话框(结束下载Request会话)
while (dataToRead > 0)
{
if (HttpContext.Current.Response.IsClientConnected)
客户端发起的http讲求之间是相互对立的,点取消后当前请求已经断开(虽然用户还在看其他的页面,但那与当前请求无关,服务端处理一个请求的超时时间不过90秒而已
程序进入了死循环。。
{
int length = stream.Read(buffer, 0, Convert.ToInt32(chunkSize));
HttpContext.Current.Response.OutputStream.Write(buffer, 0, length);
//HttpContext.Current.Response.End();
HttpContext.Current.Response.Flush();
HttpContext.Current.Response.Clear();
dataToRead -= length;
}
else
{
dataToRead = -1; //防止client失去连接
}
}

wdf618 2011-08-02
  • 打赏
  • 举报
回复
[Quote=引用 27 楼 wxr0323 的回复:]
Response.Clear();
Response.End();
[/Quote]



finally
{

//HttpContext.Current.Response.Close();
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.End();
}



这么写了,无效~~~~问题依旧~
子夜__ 2011-08-02
  • 打赏
  • 举报
回复
Response.Clear();
Response.End();
wdf618 2011-08-02
  • 打赏
  • 举报
回复
最新的代码写成了这样:



public static void FileDownload(string FilePath, string FileName, string FileType, string FileTitle)
{


try
{
string strFullFileName = FilePath + FileName;

long chunkSize = 102400; //建立一个100K的缓冲区
byte[] buffer = new byte[chunkSize];
long dataToRead = 0;//已读的字节数

using (FileStream stream = new FileStream(strFullFileName, FileMode.Open, FileAccess.Read, FileShare.Read))
{
dataToRead = stream.Length;

HttpContext.Current.Response.Clear();
HttpContext.Current.Response.ClearHeaders();
HttpContext.Current.Response.Buffer = false;

if (FileType == "")
{
FileType = FileName.Substring(FileName.LastIndexOf(".") + 1);
}
switch (FileType.ToString().ToUpper())
{
case "XLS":
HttpContext.Current.Response.ContentType = "application/ms-excel";
break;
case "DOC":
HttpContext.Current.Response.ContentType = "application/ms-word";
break;
case "TXT":
HttpContext.Current.Response.ContentType = "application/text";
break;
case "PDF":
HttpContext.Current.Response.ContentType = "application/pdf";
break;
case "GIF":
HttpContext.Current.Response.ContentType = "images/gif";
break;
case "JPG":
HttpContext.Current.Response.ContentType = "images/jpg";
break;
}
HttpContext.Current.Response.AppendHeader("Content-Disposition", "attachment;filename=" + HttpUtility.UrlEncode(FileName, System.Text.Encoding.UTF8));
HttpContext.Current.Response.AddHeader("Content-Length", dataToRead.ToString());

while (dataToRead > 0)
{
if (HttpContext.Current.Response.IsClientConnected)
{
int length = stream.Read(buffer, 0, Convert.ToInt32(chunkSize));
HttpContext.Current.Response.OutputStream.Write(buffer, 0, length);
HttpContext.Current.Response.Flush();
HttpContext.Current.Response.Clear();
dataToRead -= length;

}
else
{
dataToRead = -1; //防止client失去连接
}
}
}
}
catch (Exception ex)
{


HttpContext.Current.Response.Clear();
HttpContext.Current.Response.ClearHeaders();
HttpContext.Current.Response.Buffer = false;
HttpContext.Current.Response.ContentType = "application/octet-stream";
HttpContext.Current.Response.AppendHeader("Content-Disposition", "attachment;filename=Error.txt");
HttpContext.Current.Response.Write("下载失败!");
HttpContext.Current.Response.Flush();
HttpContext.Current.Response.End();
}
finally
{

HttpContext.Current.Response.Close();

}
}



问题依旧存在!!!

补充一个发现:在vs2010的调试状态下,该问题不存在,但在iis上运行时该问题很突出
xuexiaodong2009 2011-08-02
  • 打赏
  • 举报
回复
等牛人解决吧
wdf618 2011-08-02
  • 打赏
  • 举报
回复
[Quote=引用 23 楼 luofeng0710 的回复:]
把代码try一下,在finally里面释放资源。
[/Quote]

这样写了问题依旧存在:


public static void FileDownload(string FilePath,string FileName,string FileType, string FileTitle)
{
string strFullFileName = FilePath + FileName ;

long chunkSize = 102400; //建立一个100K的缓冲区
byte[] buffer = new byte[chunkSize];
long dataToRead = 0;//已读的字节数
FileStream stream = null;

try
{
using (stream = new FileStream(strFullFileName, FileMode.Open, FileAccess.Read, FileShare.Read))
{
dataToRead = stream.Length;

HttpContext.Current.Response.Clear();
HttpContext.Current.Response.ClearHeaders();
HttpContext.Current.Response.Buffer = true;

if (FileType == "")
{
FileType = FileName.Substring(FileName.LastIndexOf(".") + 1);
}
switch (FileType.ToString().ToUpper())
{
case "XLS":
HttpContext.Current.Response.ContentType = "application/ms-excel";
break;
case "DOC":
HttpContext.Current.Response.ContentType = "application/ms-word";
break;
case "TXT":
HttpContext.Current.Response.ContentType = "application/text";
break;
case "PDF":
HttpContext.Current.Response.ContentType = "application/pdf";
break;
case "GIF":
HttpContext.Current.Response.ContentType = "images/gif";
break;
case "JPG":
HttpContext.Current.Response.ContentType = "images/jpg";
break;
}
HttpContext.Current.Response.AppendHeader("Content-Disposition", "attachment;filename=" + HttpUtility.UrlEncode(FileName, System.Text.Encoding.UTF8));
HttpContext.Current.Response.AddHeader("Content-Length", dataToRead.ToString());

while (dataToRead > 0)
{
if (HttpContext.Current.Response.IsClientConnected)
{
int length = stream.Read(buffer, 0, Convert.ToInt32(chunkSize));
HttpContext.Current.Response.OutputStream.Write(buffer, 0, length);
HttpContext.Current.Response.Flush();
HttpContext.Current.Response.Clear();
dataToRead -= length;
}
else
{
dataToRead = -1; //防止client失去连接
}
}
}
}
catch(Exception ex)
{
SysOverlook mylog = new SysOverlook();
mylog.RecordSysError("FileDownload", ex.Message);

HttpContext.Current.Response.Clear();
HttpContext.Current.Response.ClearHeaders();
HttpContext.Current.Response.Buffer = false;
HttpContext.Current.Response.ContentType = "application/octet-stream";
HttpContext.Current.Response.AppendHeader("Content-Disposition", "attachment;filename=Error.txt");
HttpContext.Current.Response.Write("下载失败!");
HttpContext.Current.Response.Flush();
HttpContext.Current.Response.End();
}
finally
{
if (stream != null)
{
stream.Close();
}
HttpContext.Current.Response.Close();

}
}

luofeng0710 2011-08-02
  • 打赏
  • 举报
回复
把代码try一下,在finally里面释放资源。
加载更多回复(21)

62,046

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术交流专区
javascript云原生 企业社区
社区管理员
  • ASP.NET
  • .Net开发者社区
  • R小R
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

.NET 社区是一个围绕开源 .NET 的开放、热情、创新、包容的技术社区。社区致力于为广大 .NET 爱好者提供一个良好的知识共享、协同互助的 .NET 技术交流环境。我们尊重不同意见,支持健康理性的辩论和互动,反对歧视和攻击。

希望和大家一起共同营造一个活跃、友好的社区氛围。

试试用AI创作助手写篇文章吧