自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

使用XmlHttpRequest對(duì)象實(shí)現(xiàn)文件上傳進(jìn)度條

開發(fā) 后端
本文向您介紹使用XmlHttpRequest對(duì)象實(shí)現(xiàn)文件上傳進(jìn)度條。其實(shí)就是通過XmlHttpRequest對(duì)象來向服務(wù)器發(fā)出異步請(qǐng)求,并從服務(wù)器獲得數(shù)據(jù),然后用javascript來操作DOM而更新頁面。

用過ajax的朋友應(yīng)該有聽過Asp.Net XmlHttpRequest對(duì)象,ajax其實(shí)就是通過XmlHttpRequest對(duì)象來向服務(wù)器發(fā)出異步請(qǐng)求,并從服務(wù)器獲得數(shù)據(jù),然后用javascript來操作DOM而更新頁面。

本篇就是要通過XmlHttpRequest對(duì)象來實(shí)現(xiàn)實(shí)時(shí)的文件上傳進(jìn)度條顯示。

效果圖:

點(diǎn)擊圖片可以在新窗口打開

正文部分:

看過有些前輩的做法是通過設(shè)置HTTP請(qǐng)求的Refresh頭字段來定時(shí)刷新頁面從而顯示進(jìn)度,但是這樣就會(huì)帶動(dòng)整個(gè)頁面一起刷新,就算我們把進(jìn)度條做成單獨(dú)的頁面,效果仍舊不是太好。我之前試過用ajax的Timer組件,但是不知道是何原因,Timer控件在IIS下預(yù)覽時(shí)總是無法正常發(fā)揮作用。苦惱了好一陣子,懷疑是MS的BUG。最后發(fā)現(xiàn)了一個(gè)很好的替代辦法就是利用XmlHttpRequest對(duì)象來自己實(shí)現(xiàn)定時(shí)刷新,這樣每次只需向服務(wù)器請(qǐng)求很少的數(shù)據(jù),減少了對(duì)服務(wù)器的壓力,在后期的測(cè)試中,發(fā)現(xiàn)這個(gè)辦法確實(shí)很好用,而且在IIS下也一切正常(上圖就是IIS下運(yùn)行的效果)。

當(dāng)然如果光有進(jìn)度條沒有數(shù)據(jù),那這個(gè)進(jìn)度條也只能是個(gè)擺設(shè),所以我把接下來的內(nèi)容分成兩塊:進(jìn)度信息的保存、進(jìn)度的顯示

1、進(jìn)度信息的保存

首先我們要明白進(jìn)度條在這里反應(yīng)的是什么的進(jìn)度?毫無疑問是文件上傳的進(jìn)度,我們對(duì)上傳的文件數(shù)據(jù)進(jìn)行了提取,也就是說這個(gè)提取的進(jìn)度就是我們要顯示給客戶端的進(jìn)度,這樣才是文件上傳進(jìn)度條的意義。那就簡(jiǎn)單了,我們只要把已經(jīng)提取的文件大小與總的文件大小比對(duì)一下,就可以知道完成的百分比了??墒菃栴}來了,我們?nèi)绾沃郎蟼髁硕嗌倭四?答案肯定是要用一個(gè)變量來保存已經(jīng)上傳的數(shù)據(jù)量。那這個(gè)變量要放在哪里才能讓我們既可以在進(jìn)度頁面中訪問,又可以在HTTP上傳模塊中訪問呢?

大家肯定知道一般情況下,用戶在多個(gè)頁面之間訪問,會(huì)用到Session對(duì)象或URL傳值來進(jìn)行頁面之前的通信。但是前一篇所介紹的HTTP模塊并不屬于一個(gè)頁面,因此我們無法簡(jiǎn)單的應(yīng)用Session讓進(jìn)度頁面與上傳模塊實(shí)現(xiàn)通信。這里主要還是借鑒高山來客的思路:首先構(gòu)建一個(gè)用于存放文件信息的類,該類主要用來保存文件信息,如:文件名,路徑,當(dāng)前上傳的數(shù)據(jù)量,上傳時(shí)間等。然后設(shè)置一個(gè)針對(duì)某次上傳的唯一ID做為頁面中通信的暗號(hào),擁有這個(gè)暗號(hào)的頁面才能獲取對(duì)應(yīng)于某次上傳的文件信息?,F(xiàn)在已經(jīng)有了兩個(gè)變量了,接著就要使這兩個(gè)變量可以被多個(gè)頁面所使用,方法就是在上傳頁面中,將這個(gè)ID變量注冊(cè)為該頁面的一個(gè)隱藏域,這樣包含這個(gè)頁面的HTTP請(qǐng)求流中就會(huì)包含那個(gè)上傳ID。另一個(gè)類變量就保存在頁面緩存Cache中,并用上傳ID做為其編號(hào)。

現(xiàn)在假設(shè)已經(jīng)有了這么一個(gè)用于存放文件信息的類UploadFileInfo。

首先我們要在上傳頁面的PageLoad中new一個(gè)ID,然后注冊(cè)一個(gè)隱藏域用來保存此ID,同時(shí)實(shí)例化UploadFileInfo類,并將相應(yīng)的信息寫入該類,最后把該類放入Catch:

  1. if (!IsPostBack)  
  2. {  
  3. UploadFileInfo ufi = new UploadFileInfo();  
  4. ufi.strFileGuid = Guid.NewGuid().  
  5. ToString;//用GUID來表示唯一的ID;  
  6. ufi.strTempDir = Server.MapPath  
  7. ("TempUpload/" + ufi.strFileGuid + "http://");  
  8. ClientScript.RegisterHiddenField  
  9. ("UploadID", ufi.strFileGuid);  
  10. //隱藏域,名字為UploadID,值為ufi.strFileGuid  
  11. HttpContext.Current.Cache.Add(ufi.strFileGuid, ufi,   
  12. null, DateTime.Now.AddDays(10), TimeSpan.Zero,   
  13. System.Web.Caching.CacheItemPriority.High, null);//加入到Catch中  

經(jīng)過以上步驟,我們就可以在HTTP模塊中訪問了。

因?yàn)樵谶@次的HTTP請(qǐng)求流中包含了一個(gè)隱藏域,所以我們可以對(duì)獲取的HTTP請(qǐng)求流進(jìn)行分析,從而獲取相應(yīng)的上傳ID,也就是我們之前說的暗號(hào)。然后通過Cache的編號(hào)找到Cache中的文件信息對(duì)象,從而我們可以在后來的數(shù)據(jù)讀取過程中對(duì)該對(duì)象的上傳數(shù)據(jù)量進(jìn)行修改。由于是放在Cache中,加之是一個(gè)引用對(duì)象,所以對(duì)該對(duì)象修改后,其它代碼訪問到的都是最新的值。

  1. string sguid = GetUploadId(bPreloadedEnitityBody,   
  2. eContentEncode);//GetUploadId  
  3. 是自己寫的一個(gè)方法用來從請(qǐng)求流中獲取上傳ID  
  4. UploadFileInfo ufiFileInfo = (UploadFileInfo)HttpContext.  
  5. Current.Cache[sguid];//取出文件信息對(duì)象 

其它頁面如果要使用這個(gè)對(duì)象就得先獲取ID,之后就可以自由操作了。

2、文件上傳進(jìn)度條的顯示

從圖中我們可以看到,當(dāng)顯示進(jìn)度的時(shí)候,背后的頁面成灰色,并且無法響應(yīng)任何事件,有點(diǎn)類似模態(tài)窗口。這個(gè)效果大家可以在網(wǎng)上查查,還是挺容易實(shí)現(xiàn)的。我這里有一段js顯示此效果的代碼(搜集于網(wǎng)上):

  1. functionModalDialog  
  2. (name,divid,width,height,leftop,topop,color)  
  3. {  
  4. this.name=name;//名稱  
  5. this.div=divid;//要放入窗體中的元素名稱  
  6. this.width=width;//窗體寬  
  7. this.height=height;//窗體高  
  8. this.leftop=leftop;//左側(cè)位置  
  9. this.topop=topop;//上部位置  
  10. this.color=color;//整體顏色  
  11. this.show=function()//顯示窗體  
  12. {  
  13. document.all(obj.name+"_divshow").style.  
  14. width=obj.width;  
  15. document.all(obj.name+"_divshow").style.  
  16. height=obj.height;  
  17. document.all(obj.name+"_divshow").style.  
  18. left=obj.leftop;  
  19. document.all(obj.name+"_divshow").style.  
  20. top=obj.topop;  
  21. document.all(obj.name+"_mask").style.  
  22. width=document.body.clientWidth;  
  23. document.all(obj.name+"_mask").style.  
  24. height=document.body.clientHeight;  
  25. document.all(obj.name+"_divshow").style.  
  26. visibility="visible";  
  27. document.all(obj.name+"_mask").style.  
  28. visibility="visible";  
  29. }  
  30. this.close=function()//關(guān)閉窗體  
  31. {  
  32. document.all(obj.name+"_divshow").style.width=0;  
  33. document.all(obj.name+"_divshow").style.height=0;  
  34. document.all(obj.name+"_divshow").style.left=0;  
  35. document.all(obj.name+"_divshow").style.top=0;  
  36. document.all(obj.name+"_mask").style.width=0;  
  37. document.all(obj.name+"_mask").style.height=0;  
  38. document.all(obj.name+"_divshow").  
  39. style.visibility="hidden";  
  40. document.all(obj.name+"_mask").  
  41. style.visibility="hidden";  
  42. }  
  43. this.toString=function()  
  44. {  
  45. vartmp="〈divid='"+this.name+"_divshow'  
  46. style='position:absolute;left:0;top:0;z-index:10;  
  47. visibility:hidden;width:0;height:0'〉";  
  48. tmp+="〈tablecellpadding=0cellspacing=  
  49. 0border=0width=100%height=100%〉";  
  50. tmp+="〈tr〉";  
  51. tmp+="〈tdid='"+this.name+"_content'valign=top〉〈/td〉";  
  52. tmp+="〈/tr〉" 
  53. tmp+="〈/table〉";  
  54. tmp+="〈/div〉";  
  55. tmp+="〈divid='"+this.name+"_mask'  
  56. style='position:absolute;top:0;left:0;width:0;height:0;  
  57. background:#666;filter:ALPHA(opacity=50);  
  58. z-index:9;visibility:hidden'〉〈/div〉";  
  59. document.write(tmp);  
  60. document.all(this.name+"_content").insertBefore  
  61. (document.all(this.div));  
  62. }  
  63. varobj=this;  

接著講我們的重點(diǎn):如何實(shí)現(xiàn)定時(shí)局部刷新。關(guān)于XmlHttpRequest對(duì)象,我這里就不詳細(xì)講述了,提供大家一個(gè)關(guān)于此的手冊(cè)下載。為了大家更容易理解,我舉個(gè)小例子:

  1. //頁面A.aspx  
  2. functionreturnresponse(url)  
  3. {  
  4. varxmlHttp=newActiveXObject('MSXML2.xmlHttp');  
  5. if(xmlHttp!=null)  
  6. {  
  7. xmlHttp.open("GET",url,true);  
  8. //向URL指定的頁面發(fā)送GET請(qǐng)求  
  9. xmlHttp.onreadystatechange=function()  
  10. {//當(dāng)xmlHttp的readyState  
  11. 改變的時(shí)候就會(huì)引發(fā)這個(gè)事件  
  12. if(xmlHttp.readyState==4&&xmlHttp.status==200)  
  13. {//4="成功發(fā)送",200="所請(qǐng)求的頁面返回正常" 
  14. temp=xmlHttp.responseText;  
  15. //接收所請(qǐng)求頁面發(fā)回的數(shù)據(jù)  
  16. alert(temp);  
  17. }  
  18. }  
  19. xmlHttp.send(null);  
  20. }  
  21. else 
  22. {  
  23. alert("瀏覽器不支持XmlHttp.");  
  24. }  
  25. }  
  26. //URL所指向的頁面B的代碼.cs,  
  27. 當(dāng)然也可以是同一個(gè)頁面的cs  
  28. if(Request.QueryString["event"]=="test")  
  29. {  
  30. Response.Write("測(cè)試");  
  31. }  
  32.  
  33. /**//*  
  34. 然后我們?cè)贏頁中執(zhí)行returnresponse  
  35. (B.aspx?event="test");  
  36. 很快就會(huì)發(fā)現(xiàn)在A頁中彈出一個(gè)窗口,內(nèi)容是"測(cè)試"。  
  37. */ 

通過以上小例子,大家應(yīng)該已經(jīng)對(duì)該XmlHttpRequest對(duì)象有所了解了吧。為實(shí)現(xiàn)定時(shí)刷新,我把進(jìn)度條單獨(dú)放在一個(gè)頁面中(如A.aspx),通過js的setTimeout來定時(shí)執(zhí)行類似returnresponse這樣的方法,然后在A.aspx.cs代碼中獲取文件信息對(duì)象,接著通過Response來反饋進(jìn)度信息。這樣在A.aspx頁面中就可以獲取到信息,并進(jìn)行顯示了。但是執(zhí)行ActiveXObject將要花費(fèi)不少代價(jià),而且我們是定時(shí)執(zhí)行該方法,顯然會(huì)造成性能下降。在參考了構(gòu)建一個(gè)pool來管理無刷新頁面的xmlhttp對(duì)象后,決定采用這一方法,事實(shí)證明該方法實(shí)現(xiàn)文件上傳進(jìn)度條確實(shí)有效。

  1. functionxmlHttpPoolFactory()  
  2. {  
  3. this.XmlHttpPool=newArray();  
  4. this.MaxPoolLength=10;  
  5. this.Add=function()  
  6. {  
  7. if(this.XmlHttpPool.length〈this.MaxPoolLength)  
  8. {  
  9. xmlHttp=null;  
  10. if(window.XMLHttpRequest)  
  11. {//codeforallnewbrowsers  
  12. xmlHttp=newXMLHttpRequest();  
  13. }  
  14. elseif(window.ActiveXObject)  
  15. {//codeforIE5andIE6  
  16. try  
  17. {  
  18. xmlHttp=newActiveXObject('MSXML2.xmlHttp');  
  19. }  
  20. catch(e)  
  21. {  
  22. try  
  23. {  
  24. xmlHttp=newActiveXObject('Microsoft.xmlHttp');  
  25. }  
  26. catch(e2)  
  27. {  
  28. }  
  29. }  
  30. }  
  31. if(xmlHttp!=null)  
  32. {  
  33. this.XmlHttpPool.push(xmlHttp);  
  34. }  
  35. returnxmlHttp;  
  36. }  
  37. };  
  38. this.GetXmlHttp=function()  
  39. {  
  40. varxmlHttp=null;  
  41. varpool=this.XmlHttpPool;  
  42. for(vari=0;i〈pool.length;++i)  
  43. {  
  44. if(pool[i].readyState==4||pool[i].readyState==0)  
  45. {  
  46. xmlHttp=pool[i];  
  47. break;  
  48. }  
  49. }  
  50. if(xmlHttp==null)  
  51. {  
  52. returnthis.Add();  
  53. }  
  54. returnxmlHttp;  
  55. };  
  56. this.returnresponse=function(url,div)  
  57. {  
  58. varxmlHttp=this.GetXmlHttp();  
  59. varparam=div.split(',');  
  60. if(xmlHttp!=null)  
  61. {  
  62. xmlHttp.open("GET",url,true);  
  63. xmlHttp.onreadystatechange=function()  
  64. {  
  65. if(xmlHttp.readyState==4&&xmlHttp.status==200)  
  66. {//4="loaded",200="OK" 
  67. temp=xmlHttp.responseText;  
  68. vartemparray=temp.split(",");  
  69. document.getElementById(param[0]).  
  70. innerText=temparray[0];  
  71. document.getElementById(param[1]).  
  72. innerText=temparray[1]+"KB/S";  
  73. document.getElementById(param[2]).  
  74. innerHTML="  
  75. 〈tablewidth='"+temparray[2]*3+"' 〉  
  76. 〈tr 〉〈td 〉〈/td 〉〈/tr 〉〈/table 〉";  
  77. document.getElementById(param[3]).  
  78. innerText=temparray[2]+"%";  
  79. }  
  80. }  
  81. xmlHttp.send(null);  
  82. }  
  83. else 
  84. {  
  85. alert("YourbrowserdoesnotsupportxmlHttp.");  
  86. }  
  87. };  
  88. this.AportAll=function()  
  89. {  
  90. for(vari=0;i〈this.XmlHttpPool.length;++i)  
  91. {  
  92. this.XmlHttpPool[i].abort();  
  93. }  
  94. };  
  95. }  
  96. vara=newxmlHttpPoolFactory();//建立一個(gè)全局的工廠實(shí)例  
  97. varstrevent="";  
  98. functionrefresh(url,interval,div)  
  99. {//該方法我用來定時(shí)刷新,因?yàn)槌薙etTimeout還有一些其它活要干  
  100. varstr1="";  
  101. for(i=2;i〈arguments.length;i++)  
  102. {//因?yàn)榭赡苄枰⑿碌膁iv不只一個(gè),  
  103. 所以利用js的arguments來解決動(dòng)態(tài)參數(shù)的問題  
  104. if(i!=arguments.length-1)  
  105. {  
  106. str1=str1+arguments[i]+",";  
  107. }  
  108. else 
  109. {  
  110. str1=str1+arguments[i];  
  111. }  
  112. }  
  113. a.returnresponse(url,str1);//調(diào)用該方法實(shí)現(xiàn)異部通信  
  114. varstr="";  
  115. for(i=0;i〈arguments.length;i++)  
  116. {  
  117. if(i!=arguments.length-1)  
  118. str=str+"'"+arguments[i]+"',";  
  119. else 
  120. str=str+"'"+arguments[i]+"'";  
  121. }  
  122. setTimeout("refresh("+str+")",interval);//定時(shí)執(zhí)行該方法  

【編輯推薦】

  1. 配置ASP.NET AJAX概述
  2. 安裝ASP.NET AJAX的過程
  3. ASP.NET頁面請(qǐng)求原理淺析
  4. ASP.NET頁面靜態(tài)化四步走
  5. 淺析ASP.NET授權(quán)模塊
責(zé)任編輯:冰荷 來源: cnblogs
相關(guān)推薦

2009-11-24 15:23:50

PHP文件上傳進(jìn)度條

2024-08-06 14:29:37

2015-07-31 11:19:43

數(shù)字進(jìn)度條源碼

2023-12-11 17:15:05

應(yīng)用開發(fā)波紋進(jìn)度條ArkUI

2024-06-13 08:15:00

2009-08-17 15:48:47

C# WinForm進(jìn)

2009-08-17 14:41:47

C#進(jìn)度條實(shí)現(xiàn)

2009-12-25 17:58:12

WPF進(jìn)度條

2021-11-02 07:44:36

CSS 技巧進(jìn)度條

2023-11-30 11:38:29

CSS網(wǎng)頁進(jìn)度條

2011-07-05 15:16:00

QT 進(jìn)度條

2024-07-25 08:55:47

進(jìn)度條水缸進(jìn)度動(dòng)畫效果

2021-09-27 10:43:18

鴻蒙HarmonyOS應(yīng)用

2009-08-17 17:15:48

C# 進(jìn)度條效果

2012-07-13 13:52:54

Canvas

2009-08-17 14:36:15

C#進(jìn)度條實(shí)現(xiàn)

2009-06-06 18:54:02

JSP編程進(jìn)度條

2009-08-17 13:56:29

C#進(jìn)度條的使用

2012-01-17 13:58:17

JavaSwing

2023-07-18 15:49:22

HTMLCSS
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)