net文件下载所有方法.docx

上传人:小飞机 文档编号:3061873 上传时间:2023-03-10 格式:DOCX 页数:16 大小:42.91KB
返回 下载 相关 举报
net文件下载所有方法.docx_第1页
第1页 / 共16页
net文件下载所有方法.docx_第2页
第2页 / 共16页
net文件下载所有方法.docx_第3页
第3页 / 共16页
net文件下载所有方法.docx_第4页
第4页 / 共16页
net文件下载所有方法.docx_第5页
第5页 / 共16页
亲,该文档总共16页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述

《net文件下载所有方法.docx》由会员分享,可在线阅读,更多相关《net文件下载所有方法.docx(16页珍藏版)》请在三一办公上搜索。

1、net文件下载所有方法 URL方式直接下载,优点是:占用服务器资源少,速度快;缺点是: 不能准确计量下载次数,无法防止盗链,保存在数据库中的文件无法下载,常见格式的文件如.html 直接在浏览器中打开,不能直接下载。 二进制数据流输出方式,优点是:准确计量下载次数、能防盗链、所有文件格式都能直接下载而不是打开、保存在数据库中等非文件数据能以文件方式下载等;缺点是占用服务器资源多。 大文件下载原理是把文件切成小段数据流下载 public partial class FileDownLoad : System.Web.UI.Page /提供下载的文件,不编码的话文件名会乱码 private str

2、ing fileName = HttpContext.Current.Server.UrlEncode(规范.rar); private string filePath = HttpContext.Current.Server.MapPath(规范.rar); /使用TransmifFile下载文件 /* 6 微软为Response对象提供了一个新的方法TransmitFile来解决使用Response.BinaryWrite 7 下载超过400mb的文件时导致Aspnet_wp.exe进程回收而无法成功下载的问题。 8 代码如下: 9 */ protected void btnDL1_Cli

3、ck(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(Cont

4、ent-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

5、; 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分块下载文件 protecte

6、d 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.Lengt

7、h; /添加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(ch

8、unkSize); Response.OutputStream.Write(buffer, 0, length); Response.Flush; buffer = new Byte10000; dataToRead -= length; else /防止client失去连接 dataToRead = -1; catch (Exception ex) Response.Write(Error: + ex.Message); finally if (stream != null) stream.Close; Response.Close; /使用BinaryWrite下载文件,大文件效率不行 p

9、rotected 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.Content

10、Type = 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); finally if (stream != null) st

11、ream.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; try stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.

12、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.Re

13、ad(buffer, 0, Convert.ToInt32(chunkSize); Response.BinaryWrite(buffer); Response.Flush; Response.Clear; dataToRead -= length; else dataToRead = -1; catch(Exception ex) Response.Write(Error: + ex.Message); finally if (stream != null) stream.Close; Response.Close; 以上除了第四种不推荐以外,其他的都可以,但是个人感觉分块下载的要好一点。没

14、有仔细测试,所以可能有问题。 /中文标题转换 if (browser.Contains(FIREFOX) = true) outputFileName = Path.GetFileName(photo.FilePath); else outputFileName = HttpUtility.UrlEncode(Path.GetFileName(photo.FilePath); 注意:对于中文文件名要编码才能正确显示。对于长中文文件名(UTF8编码后大于153字节的中文)即使编码了,还是有问题的,大家可以参考下面的文章。 关于中文文件下载的问题,网上的咨询和答疑已经很多,我原来处理下载的代码如下

15、: response.setHeader(Content-Disposition, attachment; filename= + .URLEncoder.encode(fileName, UTF-8); 下载的程序里有了这句,一般在IE6的下载提示框上将正确显示文件的名字,无论是简体中文,还是日文。不过当时确实没有仔细测试文件名很长的中文文件名。先如今经过仔细测试,发现文字只要超过17个字,就不能下载了。经过好一番google和反复测试,总算对这个问题有了系统的认识,分列如下: 一. 通过我原来的方式,也就是先用URLEncoder编码,当中文文字超过17个时,IE6 无法下载文件。这是IE

16、的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可能在

17、年中发布。另外,Firefox 不支持这样的方式,将把编码后的%xx%xx直接作为文件名显示。 二. 我尝试使用 javamail 的MimeUtility.encode方法来编码文件名,也就是编码成 =?gb2312?B?xxxxxxxx?= 这样的形式,并从 RFC1522 中找到对应的标准支持。不过很遗憾,IE6并不支持这一个标准。我试了一下,Firefox是支持的。 三. 按网上很多人提供的解决方案:将文件名编码成ISO8859-1似乎是有效的解决方案,代码如下: response.setHeader( Content-Disposition, attachment;filename=

18、 + new String( fileName.getBytes(gb2312), ISO8859-1 ) ); 在确保附件文件名都是简体中文字的情况下,那么这个办法确实是最有效的,不用让客户逐个的升级IE。如果台湾同胞用,把gb2312改成big5就行。但现在的系统通常都加入了国际化的支持,普遍使用UTF-8。如果文件名中又有简体中文字,又有繁体中文,还有日文。那么乱码便产生了。另外,在我的电脑上Firefox(v1.0-en)下载也是乱码。 折中考虑,我结合了一、三的方式,代码片断如下: 复制代码 代码如下: String fileName = URLEncoder.encode(atta

19、.getFileName, UTF-8); /* * see */ 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 是因为它目

20、前似乎还没有有力侵食到IE的企业用户市场。影响客户买单的常常是进度,而不是兼容度。 / / 下载文件,支持大文件、续传、速度限制。支持续传的响应头Accept-Ranges、ETag,请求头Range 。 / Accept-Ranges:响应头,向客户端指明,此进程支持可恢复下载.实现后台智能传输服务,值为:bytes; / ETag:响应头,用于对客户端的初始响应,以及来自客户端的恢复请求, / 必须为每个文件提供一个唯一的ETag值,这使客户端软件能够验证它们已经下载的字节块是否仍然是最新的。 / Range:续传的起始位置,即已经下载到客户端的字节数,值如:bytes=1474560-

21、。 / 另外:UrlEncode编码后会把文件名中的空格转换中+,但是浏览器是不能理解加号为空格的,所以在浏览器下载得到的文件,空格就变成了加号; / 解决办法:UrlEncode 之后, 将 + 替换成 %20,因为浏览器将%20转换为空格 / / 当前请求的HttpContext / 下载文件的物理路径,含路径、文件名 / 下载速度:每秒允许下载的字节数 / true下载成功,false下载失败 public static bool DownloadFile(HttpContext httpContext, string filePath, long speed) bool ret = t

22、rue; 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 startBy

23、tes = 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.Cei

24、ling(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.MaxVal

25、ue) /-文件太大了- 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 / -添加重

26、要响应头、解析请求头、相关验证- 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.App

27、endHeader(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.AddHea

28、der(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;/重要:续传必须,表示局部

29、范围响应。初始下载时默认为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.R

30、esponse.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.Thr

31、ead.Sleep(sleep); catch ret = false; finally br.Close; myFile.Close; catch ret = false; return ret; /* 哈希函数将任意长度的二进制字符串映射为固定长度的小型二进制字符串。加密哈希函数有这样一个属性:在计算上不大可能找到散列为相同的值的两个不同的输入;也就是说,两组数据的哈希值仅在对应的数据也匹配时才会匹配。数据的少量更改会在哈希值中产生不可预知的大量更改。 MD5 算法的哈希值大小为 128 位。 MD5 类的 ComputeHash 方法将哈希作为 16 字节的数组返回。请注意,某些 MD5

32、 实现会生成 32 字符的十六进制格式哈希。若要与此类实现进行互操作,请将 ComputeHash 方法的返回值格式化为十六进制值。 */ / / 获取输入流的由MD5计算的Hash值,不可逆转 / / public static string GetMD5Hash(Stream inputStream) / Create a new instance of the MD5CryptoServiceProvider object. MD5 md5Hasher = MD5.Create;/不可逆转 byte data = md5Hasher.ComputeHash(inputStream); S

33、tringBuilder sb = new StringBuilder; for (int i = 0; i data.Length; i+) sb.Append(datai.ToString(x2);/十六进 / 返回十六进制的字符串 return sb.ToString; / / 验证输入流由MD5计算的Hash值 / / / / public static bool VerifyMD5Hash(Stream inputStream, string hash) string hashOfInputStream = GetMD5Hash(inputStream); StringComparer comparer = StringComparer.OrdinalIgnoreCase; if (comparer.Compare(hashOfInputStream, hash) = 0) return true; else return false;

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号