.net文件下载所有方法_第1页
.net文件下载所有方法_第2页
.net文件下载所有方法_第3页
.net文件下载所有方法_第4页
.net文件下载所有方法_第5页
已阅读5页,还剩7页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

URL方式直接下载,优点是:占用服务器资源少,速度快;缺点是: 不能准确计量下载次数,无法防止盗链,保存在数据库中的文件无法下载,常见格式的文件如.html 直接在浏览器中打开,不能直接下载。二进制数据流输出方式,优点是:准确计量下载次数、能防盗链、所有文件格式都能直接下载而不是打开、保存在数据库中等非文件数据能以文件方式下载等;缺点是占用服务器资源多。大文件下载原理是把文件切成小段数据流下载public partial class FileDownLoad : System.Web.UI.Page/提供下载的文件,不编码的话文件名会乱码private string fileName = HttpContext.Current.Server.UrlEncode(规范.rar);private string filePath = HttpContext.Current.Server.MapPath(规范.rar);/使用TransmifFile下载文件/*6微软为Response对象提供了一个新的方法TransmitFile来解决使用Response.BinaryWrite7下载超过400mb的文件时导致Aspnet_wp.exe进程回收而无法成功下载的问题。8代码如下:9*/protected void btnDL1_Click(object sender, EventArgs e)FileInfo info = new FileInfo(filePath);long fileSize = info.Length;Response.Clear();Response.ContentType = application/x-zip-compressed;Response.AddHeader(Content-Disposition, attachment;filename=+ fileName);/不指明Content-Length用Flush的话不会显示下载进度Response.AddHeader(Content-Length, fileSize.ToString();Response.TransmitFile(filePath, 0, fileSize);/Response.TransmitFile(filename);Response.Flush();Response.Close();/使用WriteFile下载文件protected void btnDL2_Click(object sender, EventArgs e)FileInfo info = new FileInfo(filePath);long fileSize = info.Length;Response.Clear();Response.ContentType = application/octet-stream;Response.AddHeader(Content-Disposition, attachement;filename= + fileName);/指定文件大小Response.AddHeader(Content-Length, fileSize.ToString();Response.WriteFile(filePath, 0, fileSize);Response.Flush();Response.Close();/使用OutputStream.Write分块下载文件protected void btnDL3_Click(object sender, EventArgs e)/指定块大小long chunkSize = 102400;/建立一个100K的缓冲区byte buffer = new bytechunkSize;/已读的字节数long dataToRead = 0;FileStream stream = null;try/打开文件stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);dataToRead = stream.Length;/添加Http头Response.ContentType = application/octet-stream;Response.AddHeader(Content-Disposition, attachement;filename= + fileName);Response.AddHeader(Content-Length, dataToRead.ToString();while (dataToRead 0)if (Response.IsClientConnected)int length = stream.Read(buffer, 0, Convert.ToInt32(chunkSize);Response.OutputStream.Write(buffer, 0, length);Response.Flush();buffer = newByte10000;dataToRead -= length;else/防止client失去连接dataToRead = -1;catch (Exception ex)Response.Write(Error: + ex.Message);finallyif (stream != null)stream.Close();Response.Close();/使用BinaryWrite下载文件,大文件效率不行protected void btnDL4_Click(object sender, EventArgs e)FileStream stream = null;try/读文件,大文件一次读入会占用大量内存stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);byte bytes = new bytestream.Length;stream.Read(bytes, 0, bytes.Length);stream.Close();/添加Http头Response.ContentType = application/octet-stream;Response.AddHeader(Content-Disposition, attachement;filename= + fileName);Response.AddHeader(Content-Length, bytes.Length.ToString();Response.BinaryWrite(bytes);Response.Flush();catch (Exception ex)Response.Write(Error: + ex.Message);finallyif (stream != null)stream.Close();Response.Close();/使用BinaryWrite分块下载文件protected void btnDL5_Click(object sender, EventArgs e)/指定区块和缓冲区long chunkSize = 102400;byte buffer = new bytechunkSize;FileStream stream = null;long dataToRead = 0;trystream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);dataToRead = stream.Length;/添加Http头Response.ContentType = application/octet-stream;Response.AddHeader(Content-Disposition, attachement;filename= + fileName);Response.AddHeader(Content-Length, dataToRead.ToString();while (dataToRead 0)if (Response.IsClientConnected)int length = stream.Read(buffer, 0, Convert.ToInt32(chunkSize);Response.BinaryWrite(buffer);Response.Flush();Response.Clear();dataToRead -= length;elsedataToRead = -1;catch(Exception ex)Response.Write(Error: + ex.Message);finallyif (stream != null)stream.Close();Response.Close();以上除了第四种不推荐以外,其他的都可以,但是个人感觉分块下载的要好一点。没有仔细测试,所以可能有问题。/中文标题转换if (browser.Contains(FIREFOX) = true) outputFileName = Path.GetFileName(photo.FilePath); else outputFileName = HttpUtility.UrlEncode(Path.GetFileName(photo.FilePath); 注意:对于中文文件名要编码才能正确显示。对于长中文文件名(UTF8编码后大于153字节的中文)即使编码了,还是有问题的,大家可以参考下面的文章。关于中文文件下载的问题,网上的咨询和答疑已经很多,我原来处理下载的代码如下:response.setHeader(Content-Disposition, attachment; filename= + .URLEncoder.encode(fileName, UTF-8);下载的程序里有了这句,一般在IE6的下载提示框上将正确显示文件的名字,无论是简体中文,还是日文。不过当时确实没有仔细测试文件名很长的中文文件名。先如今经过仔细测试,发现文字只要超过17个字,就不能下载了。经过好一番google和反复测试,总算对这个问题有了系统的认识,分列如下:一. 通过我原来的方式,也就是先用URLEncoder编码,当中文文字超过17个时,IE6 无法下载文件。这是IE的bug,参见微软的知识库文章 KB816868 。原因可能是因为ie在处理 Response Header 的时候,对header的长度限制在150字节左右。而一个汉字编码成UTF-8是9个字节,那么17个字便是153个字节,所以便会报错。微软提供了一个补丁,可以从 这里 下载。这个补丁需要先安装ie6 sp1。因为我平时勤打补丁,我的IE6版本号是 6.0.2800.1106.xpsp2_xxxxx。所以我可能已经安装过了补丁,从而可以下载,但仍然出现文件名被截断的现象。微软让我们等待IE下一个service pack的发布。我今天也上网看到了好消息,迫于firefox的压力,IE7可能在年中发布。另外,Firefox 不支持这样的方式,将把编码后的%xx%xx直接作为文件名显示。二. 我尝试使用 javamail 的MimeUtility.encode()方法来编码文件名,也就是编码成 =?gb2312?B?xxxxxxxx?= 这样的形式,并从 RFC1522 中找到对应的标准支持。不过很遗憾,IE6并不支持这一个标准。我试了一下,Firefox是支持的。三. 按网上很多人提供的解决方案:将文件名编码成ISO8859-1似乎是有效的解决方案,代码如下:response.setHeader( Content-Disposition, attachment;filename= + new String( fileName.getBytes(gb2312), ISO8859-1 ) );在确保附件文件名都是简体中文字的情况下,那么这个办法确实是最有效的,不用让客户逐个的升级IE。如果台湾同胞用,把gb2312改成big5就行。但现在的系统通常都加入了国际化的支持,普遍使用UTF-8。如果文件名中又有简体中文字,又有繁体中文,还有日文。那么乱码便产生了。另外,在我的电脑上Firefox(v1.0-en)下载也是乱码。折中考虑,我结合了一、三的方式,代码片断如下:复制代码代码如下:String fileName = URLEncoder.encode(atta.getFileName(), UTF-8);/* see /default.aspx?kbid=816868*/if (fileName.length() 150) String guessCharset = xxxx /*根据request的locale 得出可能的编码,中文操作系统通常是gb2312*/fileName = new String(atta.getFileName().getBytes(guessCharset), ISO8859-1);response.setHeader(Content-Disposition, attachment; filename= + fileName);暂且不考虑 Firefox 是因为它目前似乎还没有有力侵食到IE的企业用户市场。影响客户买单的常常是进度,而不是兼容度。/ / 下载文件,支持大文件、续传、速度限制。支持续传的响应头Accept-Ranges、ETag,请求头Range 。 / Accept-Ranges:响应头,向客户端指明,此进程支持可恢复下载.实现后台智能传输服务(BITS),值为:bytes; / ETag:响应头,用于对客户端的初始(200)响应,以及来自客户端的恢复请求, / 必须为每个文件提供一个唯一的ETag值(可由文件名和文件最后被修改的日期组成),这使客户端软件能够验证它们已经下载的字节块是否仍然是最新的。 / Range:续传的起始位置,即已经下载到客户端的字节数,值如:bytes=1474560- 。 / 另外:UrlEncode编码后会把文件名中的空格转换中+(+转换为%2b),但是浏览器是不能理解加号为空格的,所以在浏览器下载得到的文件,空格就变成了加号; / 解决办法:UrlEncode 之后, 将 + 替换成 %20,因为浏览器将%20转换为空格 / / 当前请求的HttpContext / 下载文件的物理路径,含路径、文件名 / 下载速度:每秒允许下载的字节数 / true下载成功,false下载失败 public static bool DownloadFile(HttpContext httpContext, string filePath, long speed) bool ret = true; try /-验证: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; / /定义局部变量 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 = System.IO.File.GetLastWriteTimeUtc(filePath).ToString(r); string eTag = HttpUtility.UrlEncode(fileName, Encoding.UTF8) + lastUpdateTiemStr;/便于恢复下载时提取请求头; / -验证:文件是否太大,是否是续传,且在上次被请求的日期之后是否被修改过- if (myFile.Length Int32.MaxValue) /-文件太大了- httpContext.Response.StatusCode = 413;/请求实体太大 return false; if (httpContext.Request.HeadersIf-Range != null)/对应响应头ETag:文件名+文件最后修改时间 /-上次被请求的日期之后被修改过- if (httpContext.Request.HeadersIf-Range.Replace(, ) != eTag) /文件修改过 httpContext.Response.StatusCode = 412;/预处理失败 return false; try / -添加重要响应头、解析请求头、相关验证- 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.HeadersRange != null) /-如果是续传请求,则获取续传的起始位置,即已经下载到客户端的字节数- httpContext.Response.StatusCode = 206;/重要:续传必须,表示局部范围响应。初始下载时默认为200 string range = httpContext.Request.HeadersRange.Split(new char =, - );/bytes=1474560- startBytes = Convert.ToInt64(range1);/已经下载的字节数,即本次下载的开始位置 if (startBytes = fileLength) /无效的起始位置 return false; if (startBytes 0) /-如果是续传请求,告诉客户端本次的开始字节数,总长度,以便客户端将续传数据追加到startBytes位置后- httpContext.Response.AddHeader(Content-Range, string.Format( bytes 0-1/2, startBytes, fileLength - 1, fileLength); / -向客户端发送数据块- br.BaseStream.Seek(startBytes, SeekOrigin.Begin); int maxCount = (int)Math.Ceiling(fileLength - startBytes + 0.0) / packSize);/分块下载,剩余部分可分成的块数 for (int i = 0; i 1) System.Threading.Thread.Sleep(sleep)

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论