当前位置导航:炫浪网>>网络学院>>网页制作>>ASP.NET教程

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);
}
else
Response.Write(string.Format("access is error.{0} is no exist.", path));
}
else
{
Response.Write("i need key!");
}
}代码如上所示很简单,但是注释部分,我搞了小半个小时~感觉最近手艺有点潮。
上面对代码访问http://localhost:60534/WebForm1.aspxkey=[(目录)/](文件名)
就可以访问的到了,这里面的实例都是通过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的缓冲区(如果我的想法没有错的话,原理先放在一边,事实上这些代码确实起作用了!),

共2页 首页 上一页 1 2 下一页 尾页 跳转到
相关内容
赞助商链接