在博客园上一搜就可以找到很多关于“asp.net 多线程断点续传”这方面的文章,如
但是经过我测试,没有一个是真正实用的。
在这篇文章中(http://www.cnblogs.com/bestcomy/archive/2004/08/10/31950.html)我2007年就留言:(37楼),问题到现在还没有解决。
使用如下方法测试:
1、vs2010直接启用调试。
2、把代码编译到release版本,.NET 2.0、.NET 4.0 都有,分别发布到win2003+iis6、win2008+iis7中。
3、然后用下载软件(如网络传送带、网络蚂蚁、迅雷等)访问这个提供下载的网址,下载软件开10个任务,每个任务10线程,每个任务下载限速50K左右。
结果造成asp.net给直接挂起了!尝试访问任何aspx的页面则一直处于挂起状态,即页面无法打开,IE9选项卡的那个状态标志一直在转。
一开始以为是测试系统IE9达到最大链接数了(但是开其他第三方网站是可以的),马上在其他电脑访问也不行,状态一直挂起,甚至影响到这台服务器上的其他网站,只要是aspx的全部死掉,静态的又可以正常访问(jpg、css、js等文件),服务器的cpu和内存不占多少,几乎可忽略,下载软件停止下载后又恢复了!实在是想不出什么好方法了。
再次附上我的代码,和在博客园搜到文章上的差不多:
protected void Page_Load(object sender, EventArgs e)
{
string q = Request.QueryString.Get("q");
System.IO.FileInfo f = new System.IO.FileInfo(Server.MapPath("/") + q);
int speed = 5000;//5K
FileStream file = new FileStream(f.FullName, FileMode.Open, FileAccess.Read, FileShare.Read);
BinaryReader br = new BinaryReader(file);
Response.AddHeader("Accept-Ranges", "bytes");
Response.Buffer = false;
long fileLength = file.Length;
long startBytes = 0;
int buff = 10240; //每线程10K bytes
int sleep = 1000 * buff / speed;
if (Request.Headers["Range"] != null)
{
Response.StatusCode = 206;
string[] range = Request.Headers["Range"].Split(new char[] { '=', '-' });
startBytes = Convert.ToInt64(range[1]);
}
// 添加头信息,指定文件大小,让浏览器能够显示下载进度
Response.AddHeader("Content-Length", (fileLength - startBytes).ToString());
if (startBytes != 0)
{
//支持多线程,文件分段处理
Response.AddHeader("Content-Range", string.Format(" bytes {0}-{1}/{2}", startBytes, fileLength - 1, fileLength));
}
//保持链接
Response.AddHeader("Connection", "Keep-Alive");
//设置输出流数据类型。添加头信息,为"文件下载/另存为"对话框指定默认文件名
Response.ContentType = "application/octet-stream";
Response.AddHeader("Content-Disposition", "attachment;filename=" + HttpUtility.UrlEncode(f.Name, System.Text.Encoding.UTF8));
//定义流的位置
br.BaseStream.Seek(startBytes, SeekOrigin.Begin);
long dataSent = fileLength - startBytes;
long dataLeft = 0;
while (dataLeft < dataSent)
{
if (Response.IsClientConnected)
{
Response.BinaryWrite(br.ReadBytes(buff));
dataLeft += buff;
Response.Flush();
Thread.Sleep(sleep);
}
else
{
dataSent = -1;
}
}
Response.End();
br.Close();
file.Close();
}