欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

asp.net 文件下载实现代码

程序员文章站 2024-03-07 23:26:57
复制代码 代码如下:public static bool downloadfile(httpcontext httpcontext, string filepath, lo...
复制代码 代码如下:

public static bool downloadfile(httpcontext httpcontext, string filepath, long speed)
{
bool ret = true;
try
{
#region--验证:httpmethod,请求的文件是否存在
switch (httpcontext.request.httpmethod.toupper())
{ //目前只支持get和head方法
case "get":
case "head":
break;
default:
httpcontext.response.statuscode = 501;
return false;
}
if (!file.exists(filepath))
{
httpcontext.response.statuscode = 404;
return false;
}
#endregion
#region 定义局部变量
long startbytes = 0;
int packsize = 1024 * 10; //分块读取,每块10k bytes
string filename = path.getfilename(filepath);
filestream myfile = new filestream(filepath, filemode.open, fileaccess.read, fileshare.readwrite);
binaryreader br = new binaryreader(myfile);
long filelength = myfile.length;
int sleep = (int)math.ceiling(1000.0 * packsize / speed);//毫秒数:读取下一数据块的时间间隔
string lastupdatetiemstr = file.getlastwritetimeutc(filepath).tostring("r");
string etag = httputility.urlencode(filename, encoding.utf8) + lastupdatetiemstr;//便于恢复下载时提取请求头;
#endregion
#region--验证:文件是否太大,是否是续传,且在上次被请求的日期之后是否被修
if (myfile.length > int32.maxvalue)
{//-------文件太大了-------
httpcontext.response.statuscode = 413;//请求实体太大
return false;
}

if (httpcontext.request.headers["if-range"] != null)//对应响应头etag:文件名+文件最后修改时间
{
//----------上次被请求的日期之后被修改过--------------
if (httpcontext.request.headers["if-range"].replace("\"", "") != etag)
{//文件修改过
httpcontext.response.statuscode = 412;//预处理失败
return false;
}
}
#endregion
try
{
#region -------添加重要响应头、解析请求头、相关验证-------------------
httpcontext.response.clear();
httpcontext.response.buffer = false;
httpcontext.response.addheader("content-md5", getmd5hash(myfile));//用于验证文件
httpcontext.response.addheader("accept-ranges", "bytes");//重要:续传必须
httpcontext.response.appendheader("etag", "\"" + etag + "\"");//重要:续传必须
httpcontext.response.appendheader("last-modified", lastupdatetiemstr);//把最后修改日期写入响应
httpcontext.response.contenttype = "application/octet-stream";//mime类型:匹配任意文件类型
httpcontext.response.addheader("content-disposition", "attachment;filename=" + httputility.urlencode(filename, encoding.utf8).replace("+", "%20"));
httpcontext.response.addheader("content-length", (filelength - startbytes).tostring());
httpcontext.response.addheader("connection", "keep-alive");
httpcontext.response.contentencoding = encoding.utf8;
if (httpcontext.request.headers["range"] != null)
{//------如果是续传请求,则获取续传的起始位置,即已经下载到客户端的字节数------
httpcontext.response.statuscode = 206;//重要:续传必须,表示局部范围响应。初始下载时默认为200
string[] range = httpcontext.request.headers["range"].split(new char[] { '=', '-' });//"bytes=1474560-"
startbytes = convert.toint64(range[1]);//已经下载的字节数,即本次下载的开始位置
if (startbytes < 0 || startbytes >= filelength)
{//无效的起始位置
return false;
}
}
if (startbytes > 0)
{//------如果是续传请求,告诉客户端本次的开始字节数,总长度,以便客户端将续传数据追加到startbytes位置后----------
httpcontext.response.addheader("content-range", string.format(" bytes {0}-{1}/{2}", startbytes, filelength - 1, filelength));
}
#endregion
#region -------向客户端发送数据块-------------------
br.basestream.seek(startbytes, seekorigin.begin);
int maxcount = (int)math.ceiling((filelength - startbytes + 0.0) / packsize);//分块下载,剩余部分可分成的块数
for (int i = 0; i < maxcount && httpcontext.response.isclientconnected; i++)
{//客户端中断连接,则暂停
httpcontext.response.binarywrite(br.readbytes(packsize));
httpcontext.response.flush();
if (sleep > 1) thread.sleep(sleep);
}
#endregion
}
catch
{
ret = false;
}
finally
{
br.close();
myfile.close();
}
}
catch
{
ret = false;
}
return ret;
}