Asp.Net 上传大文件专题(4)--利用ajax技术显示上传进度-阿里云开发者社区

开发者社区> 嗯哼9925> 正文

Asp.Net 上传大文件专题(4)--利用ajax技术显示上传进度

简介:
+关注继续查看
    我们介绍了如何从HTTP请求流中将数据部分进行截取,同时将数据相关信息进行保存。

      本篇概述:
      用过ajax的朋友应该有听过XmlHttpRequest对象,ajax其实就是通过XmlHttpRequest对象来向服务器发出异步请求,并从服务器获得数据,然后用javascript来操作DOM而更新页面。
      本篇就是要通过XmlHttpRequest对象来实现实时的进度显示。

      效果图:


      正文部分:
      看过有些前辈的做法是通过设置HTTP请求的Refresh头字段来定时刷新页面从而显示进度,但是这样就会带动整个页面一起刷新,就算我们把进度条做成单独的页面,效果仍旧不是太好。我之前试过用ajax的Timer组件,但是不知道是何原因,Timer控件在IIS下预览时总是无法正常发挥作用。苦恼了好一阵子,怀疑是MS的BUG。最后发现了一个很好的替代办法就是利用XmlHttpRequest对象来自己实现定时刷新,这样每次只需向服务器请求很少的数据,减少了对服务器的压力,在后期的测试中,发现这个办法确实很好用,而且在IIS下也一切正常(上图就是IIS下运行的效果)。
      当然如果光有进度条没有数据,那这个进度条也只能是个摆设,所以我把接下来的内容分成两块:进度信息的保存、进度的显示
      
      1、进度信息的保存
      首先我们要明白进度条在这里反应的是什么的进度?毫无疑问是文件上传的进度喽~~在上一篇中,我们对上传的文件数据进行了提取,也就是说这个提取的进度就是我们要显示给客户端的进度。那就简单了,我们只要把已经提取的文件大小与总的文件大小比对一下,就可以知道完成的百分比了。可是问题来了,我们如何知道上传了多少了呢?答案肯定是要用一个变量来保存已经上传的数据量。那这个变量要放在哪里才能让我们既可以在进度页面中访问,又可以在HTTP上传模块中访问呢?
      大家肯定知道一般情况下,用户在多个页面之间访问,会用到Session对象或URL传值来进行页面之前的通信。但是前一篇所介绍的HTTP模块并不属于一个页面,因此我们无法简单的应用Session让进度页面与上传模块实现通信。这里主要还是借鉴高山来客的思路:首先构建一个用于存放文件信息的类,该类主要用来保存文件信息,如:文件名,路径,当前上传的数据量,上传时间等。然后设置一个针对某次上传的唯一ID做为页面中通信的暗号,拥有这个暗号的页面才能获取对应于某次上传的文件信息。现在已经有了两个变量了,接着就要使这两个变量可以被多个页面所使用,方法就是在上传页面中,将这个ID变量注册为该页面的一个隐藏域,这样包含这个页面的HTTP请求流中就会包含那个上传ID。另一个类变量就保存在页面缓存Cache中,并用上传ID做为其编号。
      现在假设已经有了这么一个用于存放文件信息的类UploadFileInfo。
      首先我们要在上传页面的PageLoad中new一个ID,然后注册一个隐藏域用来保存此ID,同时实例化UploadFileInfo类,并将相应的信息写入该类,最后把该类放入Cache:
      

复制代码
if (!IsPostBack)
ExpandedBlockStart.gif
{
    UploadFileInfo ufi 
= new UploadFileInfo();
    ufi.strFileGuid 
= Guid.NewGuid().ToString;//用GUID来表示唯一的ID;
    ufi.strTempDir 
= Server.MapPath("TempUpload/" + ufi.strFileGuid + "//");
    ClientScript.RegisterHiddenField(
"UploadID", ufi.strFileGuid);//隐藏域,名字为UploadID,值为ufi.strFileGuid
    HttpContext.Current.Cache.Add(ufi.strFileGuid, ufi, null, DateTime.Now.AddDays(10), TimeSpan.Zero, System.Web.Caching.CacheItemPriority.High, null);//加入到Catch中
}
复制代码


      经过以上步骤,我们就可以在HTTP模块中访问了。
      因为在这次的HTTP请求流中包含了一个隐藏域,所以我们可以对获取的HTTP请求流进行分析,从而获取相应的上传ID,也就是我们之前说的暗号。然后通过Cache的编号找到Cache中的文件信息对象,从而我们可以在后来的数据读取过程中对该对象的上传数据量进行修改。由于是放在Cache中,加之是一个引用对象,所以对该对象修改后,其它代码访问到的都是最新的值。

string sguid = GetUploadId(bPreloadedEnitityBody, eContentEncode);//GetUploadId是自己写的一个方法用来从请求流中获取上传ID
UploadFileInfo ufiFileInfo = (UploadFileInfo)HttpContext.Current.Cache[sguid];//取出文件信息对象


      其它页面如果要使用这个对象就得先获取ID,之后就可以自由操作了。

      2、进度的显示
      从图中我们可以看到,当显示进度的时候,背后的页面成灰色,并且无法响应任何事件,有点类似模态窗口。这个效果大家可以在网上查查,还是挺容易实现的。我这里有一段js显示此效果的代码(搜集于网上):

ContractedBlock.gifModalDialog


      接着讲我们的重点:如何实现定时局部刷新。
      关于XmlHttpRequest对象,我这里就不详细讲述了,提供大家一个关于此的手册下载。为了大家更容易理解,我举个小例子:
  

ContractedBlock.gif小例子

    

      通过以上小例子,大家应该已经对该对象有所了解了吧。为实现定时刷新,我把进度条单独放在一个页面中(如A.aspx),通过js的setTimeout来定时执行类似returnresponse这样的方法,然后在A.aspx.cs代码中获取文件信息对象,接着通过Response来反馈进度信息。这样在A.aspx页面中就可以获取到信息,并进行显示了。但是执行ActiveXObject将要花费不少代价,而且我们是定时执行该方法,显然会造成性能下降。在参考了构建一个pool来管理无刷新页面的xmlhttp对象后,决定采用这一方法,事实证明该方法确实有效。

ContractedBlock.gif利用pool后的代码

       到这就差不多整个专题都结束了,接下来几天,我会把代码稍微调整下,然后传上来。 

       由于这段时间要上班,实在抽不出时间来整理,如果大家需要可以先拿去看看。不过代码写的有点乱,而且有些功能也没有完善,时间实在太少,大家见谅。

       粗糙的工程








本文转自stg609博客园博客,原文链接:http://www.cnblogs.com/stg609/archive/2008/08/04/1259469.html,如需转载请自行联系原作者

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
阿里云服务器怎么设置密码?怎么停机?怎么重启服务器?
如果在创建实例时没有设置密码,或者密码丢失,您可以在控制台上重新设置实例的登录密码。本文仅描述如何在 ECS 管理控制台上修改实例登录密码。
7778 0
你以为的ASP.NET文件上传大小限制是你以为的吗
原文:你以为的ASP.NET文件上传大小限制是你以为的吗 我们以为的文件大小限制 我们大家都知道ASP.NET为我们提供了文件上传服务器控件FileUpload,默认情况下可上传的最大文件为4M,如果要改变可上传文件大小限制,那么我们可以在web.config中的httpRuntime元素中添加maxRequestLength属性设置大小,同时为了支持大文件上传超时可以添加executionTimeout属性设置超时时间。
1067 0
asp.net 上传大文件大小控制方案
.NET默认允许上传4M的文件。 修改 Machine.config 文件,改动MaxRequestLength 参数的值。
900 0
bootstrap改变上传文件按钮样式,并显示已上传文件名
参考博文:  html中,文件上传时使用的的样式自定义html中默认样式很丑,这里用了Bootstrap按钮的样式,并获取文件名显示在其右侧 闲话少叙,直接上代码: 任务数据              上传                   未上传文件 function loadFile(file){     $$("#filename").
4229 0
fileapi ajax上传图片显示
fileapi,加载图片,并且显示。 先new 一个fileReader。 主要方法 // try sending var reader = new FileReader(); reader.
773 0
+关注
4716
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载