传奇般的巴别塔

在代码中游走,在夜幕里吟唱,徘徊在城市的边缘由着理性和感性纠缠、厮杀
posts - 3, comments - 28, trackbacks - 0, articles - 0

2008年6月16日

     最近在写一个Web版本的文件管理器,正好又有朋友问起web页面上面可以让图片也变成下载模式的那种链接方式在ASP.NET里面怎么实现,我给他写了一个大概,觉得也应该当作笔记贴出来,帮他写的时候,突然发现很多问题自己也不是明白,所以逐一查找了一番,贴出来和大家分享!

     应用场景,很多时候都有盗链等各种各样的原因,用ASP.NET呢,最基本的一个问题,我的所有数据文件都保存在App_Data,这个文件夹和配置文件Web.Config一样,直接是无法访问其中内容的,所以如果里面上传了文件,无论是图片,还是压缩包,想下载就要通过某个点Response.WriteFile出去,不过在讨论的时候又发现了一些新的内容,如下:

首先,是下载的基础,Http Header 的做两个设置:

  1. Content-Type : (这个~很无语的东西,每次都记不住,现查!Wiki)
              application/octet-stream           万金油型,什么文件都适合!
              application/x-zip-compressed      专门针对Zip文件的,但是在某些情况下有奇效,这个后面讲
  2. 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); } else Response.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目录内容浏览和文件下载的示例,还有很多缺陷,比如说没有针对权限作出甄别监测,当然需要只是简单的管理权限,那就在<location>节点里面配置一下也好,Web.config的配置代码如下:

<httpHandlers>
    <add verb="GET" path="adbrowser.o" type="I.HttpHandler.AppDataBrowser,I.Controls" />
<add verb="*" path="download.o" type="I.HttpHandler.Download,I.Controls" />
</httpHandlers>

点击下载I.Controls.rar

备选版本:

所谓高级版,其实又算是一个微软的私有定义了,使用TransmitFile可以分段输出,大家都知道IE支持断点续传的,但是有时候当我们下载一半中断之后,我们再去请求的时候,突然IE的普通下载就变成续传型了,很神奇,能碰到机会和出去逛街捡了一万块钱的几率相当。传说中在IE请求的时候会传入时会附加一个Header,叫做Range用来框定目前下载文件的长度,和已下载的字节位置,然后结合creation-date,modification-date去判断是否可以续连上一次下载的内容接着下载,但是这个又有一个新的麻烦的点,首先我用Reflector拆开TransmitFile看了一下,与WriteFile一样的实现机制,依然会有资源占有的问题,然后就是只针对IE,用Fiddler抓了一上午都没有发现FF或Opera之流,但是没有对迅雷或者是快车进行监测,不知道这个会不会再下载工具中有什么实际用途,最好的解决方案就是把range信息自己摘出来解析,然后自己去附加日期信息,用第二种方式缓冲输出。设想是这样的,因为我对HTTP请求不是很了解,请了解的站出来,指点一下。这个版本没有写,就是思考而已,有朋友感兴趣可以实现以下,记得告诉我什么感觉~

posted @ 2008-06-16 11:03 evanescencex 阅读(2988) | 评论 (11)编辑

2008年6月4日

      自从上大学就学会了用手机看书,而且看得还很上瘾,每晚睡前都要看一会儿,以前每到书荒都要到处搜罗txt,现在读书网站如雨后春笋,就想如果能直接转换,那岂不是很爽~其实我觉得现在聪明人还是很多的,所以肯定已经有兄弟提前搞定了,就先G了一下,果然有好几种逐一试用了一下,功能上还是多有遗憾,所以就决定自己动手做一个,下面截图是第一个功能预览版(其实是因为LP大人每天催稿得产物:)~幸亏没遇上这样的上司,苦啊~),目前这个就是实现了[新浪读书]和[QQ读书]两个读书频道,而且暂不支持收费书籍,程序还有些不稳定,没有对异常进行处理,只是当作基础功能预览。

待解决的问题(不断更新,有知道的朋友,记得留一句):
  • 输出PDF文件:嵌入字体、添加目录、书签;

 

  • 支持新浪读书频道(domian:book.sina.com.cn),QQ读书频道(domian:book.qq.com)
  • 内嵌IE内核多选项卡浏览器
  • 自动排版,纯文本输出
  • 支持单文本和按章节切割输出
  • 多线程下载书籍
  • 运行需.NET Framework 3.5支持,支持Windows XP/Vista,暂不支持Windows 2003操作系统

 e.Capturer.rar

暂收集需求如下(各位不要光看热闹,也说点什么需求):

  • 高级收藏夹(在基本收藏家的功能之上添加IE和FF共享载入和导入功能)
  • 订阅,针对网络原创和连载部分添加监控、订阅功能
  • 插件化抓取插件,支持更多的网站
  • 多平台运行,Windows 2003不能运行的问题已解决
  • Web版本
  • 支持多设备导出,包含各种手机和PSP平台,各种格式OOXML、PDF、TXT...

发散思维大家一起来讲需求,此项目的代码,我整理整理过段时间释出...有不嫌乱的兄弟,留Email,发给你们。

posted @ 2008-06-04 17:58 evanescencex 阅读(579) | 评论 (13)编辑

2008年5月24日

        早上起来的时候突然发现这个世界又复杂又简单,在本场面试当中我恰当的表现,引起了他们的重视,又恰当的进入了last line,但是我没有在最后一刻如我所述的保持住自己的所谓的稳定和专注,让我失去了这次的机会,这个和别人无关,我承认自己这次依然很任性,现在对于事物和自我的把持越来越无力了!在我看来这次面试应该是以下的过程:
        第一,我的简历和我笔试的表现引起了他们的兴趣,我获得了面试的机会;
        第二,第一次面试当中,我做了一番专注和专业化的讨论,以及一些其他的交流,他们觉得我的表达和我的专业性不符合(似乎大家常理上都觉得好程序员要沉默,能侃的程序员就扯淡了!)
        我想在这个之后应该就是一个套儿了!
        第三,产品部门主管约见我,开始对我施展诱术,给了我一个不会很枯燥且很工作量化宽松的职位(诱饵),在这里提到了技术,这个应该算是他给的一个让我退缩的提示,但是我这个时候可能有点像不知死活而去扑抢的贪食者,无视他的提示以及其他可能我为察觉的提示,而满口答应,并且还狠狠的吃了几口,后面就总裁约见,这天状态不佳,以为就是听汇报,有点没精打采的和他聊了几句,然后他给了一个提示,告诉我会怎么去辞去我,一个小故事,和一个小理论,呵呵,权当玩笑~半个小时后,他们依计由人事主管出面,来通杀我,用我不能接受的理由和要求,激我去联想刚才听过的小故事,然后,呵呵,我输了,走人!
         我承认我是一个贪婪者,现在还一直没有给过自己一个真正的约束,而这次面试,是一个绝大的教训!也突然让我找到了自己的目标和动力。努力,努力~谢谢这两周来面试我,已经你们策划的这个圈,不管你们是故意的,还是我多心了,但是经过这次,我的的确确看到了自己所欠缺的还有很多,任职并非创业,我还有很多需要学习的东西。
BTW:贴以下我的简历,顺便看过有需要的公司,call me , thx。
固定链接: http://www.dotags.com/profile.html

posted @ 2008-05-24 01:05 evanescencex 阅读(57) | 评论 (0)编辑

2008年3月31日

又一次开博!
为什么要用又呢?
不是我开了很多个博客,
是因为这个博客我就开了不止一次了!
      就像朋友说的那样,我是一个在常温下极不稳定的元素,这个博客应该是去年很早的时候就注册了,本来是很想写点什么,但是转了一次原来Blog的文章之后就再没有写了,那个时候比较懒,无所事事,后来清空了一次,本来想写点什么,但是太忙了!!!真的忙到不行,连我写了很久的八卦博客都停了,粗算起来我可能有大约一年多没写东西了吧,都不知道该从何说起了,这次回来北京,就做好了待一些年的准备,收拾收拾了近一年没有住的屋子,整理了一下我心爱的书,挑了一些拿了出来,自从搬家到这边有些书箱都没有开封过,上周去宜家淘了一个书架,算是给它们安个小窝吧。也不知道该说些什么,具体的中心思想就说,我回来了。
不多说了,上图鸟:

还有我要上主页,骚扰,哈哈哈...

posted @ 2008-03-31 01:49 evanescencex 阅读(87) | 评论 (0)编辑