<dfn id="w48us"></dfn><ul id="w48us"></ul>
  • <ul id="w48us"></ul>
  • <del id="w48us"></del>
    <ul id="w48us"></ul>
  • 通過(guò)Asp.Net的服務(wù)器控件上傳文件總結(jié)

    時(shí)間:2024-09-02 13:20:24 ASP 我要投稿
    • 相關(guān)推薦

    通過(guò)Asp.Net的服務(wù)器控件上傳文件總結(jié)

      相信通過(guò)Asp.Net的服務(wù)器控件上傳文件在簡(jiǎn)單不過(guò)了,通過(guò)AjaxToolkit控件實(shí)現(xiàn)上傳進(jìn)度也不是什么難事,為什么還要自己辛辛苦苦來(lái) 實(shí)現(xiàn)呢?我并不否認(rèn)”拿來(lái)主義“,只是我個(gè)人更喜歡凡是求個(gè)所以然。本篇將闡述通過(guò)Html,IHttpHandler和 IHttpAsyncHandler實(shí)現(xiàn)文件上傳和上傳進(jìn)度的原理,希望對(duì)你有多幫助。

    通過(guò)Asp.Net的服務(wù)器控件上傳文件總結(jié)

      效果圖:

      本文涉及到的知識(shí)點(diǎn):

      1.前臺(tái)用到Html,Ajax,JQuery,JQuery UI

      2.后臺(tái)用到一般處理程序(IHttpHandler)和一般異步處理程序(IHttpAsyncHandler),并涉及到”推模式“

      一、創(chuàng)建Html網(wǎng)頁(yè)

      1、在創(chuàng)建的Web工程中添加一個(gè)Html文件,命名為UploadFile.htm,在頭文件中引入JQuery,JQuery UI

      復(fù)制代碼 代碼如下:

      二、實(shí)現(xiàn)文件上傳

      添加一個(gè)一般處理程序,命名為UploadFileHandler.ashx

      復(fù)制代碼 代碼如下:

      public void ProcessRequest(HttpContext context)

      {

      //如果提交的文件名是空,則不處理

      if (context.Request.Files.Count == 0 || string.IsNullOrWhiteSpace(context.Request.Files[0].FileName))

      return;

      //獲取文件流

      Stream stream = context.Request.Files[0].InputStream;

      //獲取文件名稱

      string fileName = Path.GetFileName(context.Request.Files[0].FileName);

      //聲明字節(jié)數(shù)組

      byte[] buffer;

      //為什么是4096呢?這是操作系統(tǒng)中最小的分配空間,如果你的文件只有100個(gè)字節(jié),其實(shí)它占用的空間是4096個(gè)字節(jié)

      int bufferSize = 4096;

      //獲取上傳文件流的總長(zhǎng)度

      long totalLength = stream.Length;

      //已經(jīng)寫入的字節(jié)數(shù),用于做上傳的百分比

      long writtenSize = 0;

      //創(chuàng)建文件

      using (FileStream fs = new FileStream(@"C:" + fileName, FileMode.Create, FileAccess.Write))

      {

      //如果寫入文件的字節(jié)數(shù)小于上傳的總字節(jié)數(shù),就一直寫,直到寫完為止

      while (writtenSize < totalLength)

      {

      //如果剩余的字節(jié)數(shù)不小于最小分配空間

      if (totalLength - writtenSize >= bufferSize)

      {

      //用最小分配空間創(chuàng)建新的字節(jié)數(shù)組

      buffer = new byte[bufferSize];

      }

      else

      //用剩余的字節(jié)數(shù)創(chuàng)建字節(jié)數(shù)組

      buffer = new byte[totalLength - writtenSize];

      //讀取上傳的文件到字節(jié)數(shù)組

      stream.Read(buffer, 0, buffer.Length);

      //將讀取的字節(jié)數(shù)組寫入到新建的文件流中

      fs.Write(buffer, 0, buffer.Length);

      //增加寫入的字節(jié)數(shù)

      writtenSize += buffer.Length;

      //計(jì)算當(dāng)前上傳文件的百分比

      long percent = writtenSize * 100 / totalLength;

      }

      }

      }

      在form中添加action和method屬性,修改之后的

      復(fù)制代碼 代碼如下:

      這樣文件上傳就完成了。

      三、實(shí)現(xiàn)文件上傳的進(jìn)度顯示

      我的思路:

      文件上傳的處理過(guò)程中,是不可以在處理過(guò)程中將信息傳回客戶端的,只有當(dāng)所有的處理都完畢之后才會(huì)傳回客戶端,所以如果是在上面的處理程序中寫 入context.Response.Write(percent);是不可能得到處理的過(guò)程,只能等到處理結(jié)束后,客戶端一次性得到所有的值。

      要想得到處理過(guò)程中的值,我的解決是這樣,在文件上傳時(shí),要開啟另一個(gè)請(qǐng)求,來(lái)獲取進(jìn)度信息。而這個(gè)請(qǐng)求是異步的,我指的是客戶端異步請(qǐng)求和服 務(wù)端異步處理。因?yàn)橐婕暗絻蓚(gè)不同的請(qǐng)求處理程序之間信息的傳遞,將"處理文件上傳的程序"得到的進(jìn)度信息傳遞給"處理進(jìn)度請(qǐng)求的程序",而"處理進(jìn)度 請(qǐng)求的處理程序"要依賴于"處理文件上傳的處理程序"。處理圖:

      首先客戶端同時(shí)(幾乎是)發(fā)出兩個(gè)請(qǐng)求,一個(gè)是文件上傳,一個(gè)是進(jìn)度請(qǐng)求。由于"處理請(qǐng)求進(jìn)度的程序"是異步處理的,當(dāng)該程序沒有信息發(fā)給客戶 端時(shí),我們讓它處于等待狀態(tài),這里有點(diǎn)像Tcp,這樣客戶端跟服務(wù)器就一直處于連接狀態(tài)。當(dāng)"處理文件上傳的程序"開始處理時(shí),通過(guò)把進(jìn)度值賦值給"處理 請(qǐng)求進(jìn)度程序"的異步操作的狀態(tài),并觸發(fā)"處理請(qǐng)求進(jìn)度的程序"返回值給客戶端。客戶端獲取進(jìn)度值,并處理。這樣一次請(qǐng)求進(jìn)度值的請(qǐng)求就結(jié)束了,我們知道 服務(wù)器是不會(huì)主動(dòng)給客戶端發(fā)送信息的,只有客戶端請(qǐng)求,服務(wù)器才會(huì)響應(yīng)。顯然,要想在文件保存的過(guò)程中向客戶端發(fā)送進(jìn)度信息,客戶端得到每得到一個(gè)返回結(jié) 果,都是一次請(qǐng)求。為了得到連續(xù)的請(qǐng)求值,客戶端再向"處理請(qǐng)求進(jìn)度的程序"發(fā)出請(qǐng)求,依次循環(huán),知道文件上傳結(jié)束。

      技術(shù)實(shí)現(xiàn):

      異步處理用到接口IHttpAsyncHandler,新建一個(gè)一般處理程序,命名為RequestProgressAsyncHandler.ashx,將默認(rèn)的接口改為IHttpAsyncHandler

      復(fù)制代碼 代碼如下:

      public class RequestProgressAsyncHandler : IHttpAsyncHandler

      {

      public void ProcessRequest(HttpContext context)

      {

      }

      public bool IsReusable

      {

      get

      {

      return false;

      }

      }

      #region IHttpAsyncHandler 成員

      public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)

      {

      throw new NotImplementedException();

      }

      public void EndProcessRequest(IAsyncResult result)

      {

      throw new NotImplementedException();

      }

      #endregion

      }

      BeginProcessRequest和EndProcessRequest是兩個(gè)核心的方法,其他的兩個(gè)不用處理。當(dāng)該處理程序處理請(qǐng)求 時(shí),BeginProcessRequest是第一個(gè)被調(diào)用的函數(shù),返回一個(gè)包含異步狀態(tài)信息的對(duì)象,該對(duì)象是IAsyncResult類型,是實(shí)現(xiàn)異步 的關(guān)鍵,用于控制什么時(shí)候調(diào)用EndProcessRequest來(lái)結(jié)束處理程序的等待狀態(tài),BeginProcessRequest被調(diào)用之后,程序就 處于等待狀態(tài)。EndProcessRequest是在結(jié)束請(qǐng)求時(shí)的處理函數(shù),通過(guò)該函數(shù)可以向客戶端寫入信息。

      實(shí)現(xiàn)接口IAsyncResult

      復(fù)制代碼 代碼如下:

      public class AsyncResult : IAsyncResult

      {

      // 標(biāo)示異步處理的狀態(tài)

      private bool isComplete = false;

      //保存異步處理程序中的Http上下文

      private HttpContext context;

      //異步回調(diào)的委托

      private AsyncCallback callback;

      ///

      /// 獲取或設(shè)置保存下載文件的百分比數(shù)值部分

      ///

      public long PercentNumber;

      public AsyncResult(HttpContext context, AsyncCallback callback)

      {

      this.context = context;

      this.callback = callback;

      }

      ///

      /// 向客戶端寫入信息

      ///

      public void Send()

      {

      this.context.Response.Write(PercentNumber);

      }

      ///

      /// 完成異步處理,結(jié)束請(qǐng)求

      ///

      public void DoCompleteTask()

      {

      if (callback != null)

      callback(this);//會(huì)觸發(fā)處理程序中的EndProcessRequest函數(shù),結(jié)束請(qǐng)求

      this.isComplete = true;

      }

      #region IAsyncResult 成員

      public object AsyncState

      {

      get { return null; }

      }

      public System.Threading.WaitHandle AsyncWaitHandle

      {

      get { return null; }

      }

      public bool CompletedSynchronously

      {

      get { return false; }

      }

      public bool IsCompleted

      {

      get { return isComplete; }

      }

      #endregion

      }

      修改 RequestProgressAsyncHandler.ashx文件:

      復(fù)制代碼 代碼如下:

      public class RequestProgressAsyncHandler : IHttpAsyncHandler

      {

      ///

      /// 保存異步處理狀態(tài)信息的集合

      ///

      public static ListAsyncResults = new List();

      public void ProcessRequest(HttpContext context)

      {

      }

      public bool IsReusable

      {

      get

      {

      return false;

      }

      }

      #region IHttpAsyncHandler 成員

      public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)

      {

      AsyncResult result = new AsyncResult(context, cb);

      AsyncResults.Add(result);

      return result;

      }

      public void EndProcessRequest(IAsyncResult result)

      {

      //保證集合中只用一個(gè)元素

      AsyncResults.Clear();

      AsyncResult ar = (AsyncResult)result;

      ar.Send();

      }

      #endregion

      }

      在UploadFileHandler.ashx添加如下代碼:

      復(fù)制代碼 代碼如下:

      private static void SendPercentToClient(long percent)

      {

      //當(dāng)上傳完畢后,保證處理程序能向客戶端傳回

      while (RequestProgressAsyncHandler.AsyncResults.Count == 0 && percent == 100)

      {

      }

      //因?yàn)楸咎幚沓绦蚝?quot;處理請(qǐng)求進(jìn)度的程序"是并發(fā)的,不能保證RequestProgressAsyncHandler.AsyncResults一定含有子項(xiàng)

      if (RequestProgressAsyncHandler.AsyncResults.Count != 0)

      {

      RequestProgressAsyncHandler.AsyncResults[0].PercentNumber = percent;

      RequestProgressAsyncHandler.AsyncResults[0].DoCompleteTask();

      }

      }

      在函數(shù)ProcessRequest中加入以上方法:

      復(fù)制代碼 代碼如下:

      ...

      ...

      //計(jì)算當(dāng)前上傳文件的百分比

      long percent = writtenSize * 100 / totalLength;

      SendPercentToClient(percent);

      服務(wù)端OK!修改客戶端,添加JS處理函數(shù):

      復(fù)制代碼 代碼如下:

      function RequestProgress() {

      $.post("RequestProgressAsyncHandler.ashx", function (data, status) {

      if (status == "success") {

      $("#progressValue").text(data + "%");

      data = parseInt(data);

      $("#progressBar").progressbar({ value: data });//JQuery UI 設(shè)置進(jìn)度條值

      //如果進(jìn)度不是 100,則重新請(qǐng)求

      if (data != 100) {

      RequestProgress();

      }

      }

      });

      }

      在form中添加事件omsubmit的處理函數(shù)為RequestProgress

      復(fù)制代碼 代碼如下:

      補(bǔ)充幾點(diǎn):

      1.默認(rèn)Asp.Net允許的上傳文件的大小是4M,可以在Web.config中修改其大小限制

      復(fù)制代碼 代碼如下:

      maxRequestLength的單位是KB

      2.在IE 8.0測(cè)試中,在文件上傳完畢后,狀態(tài)欄還處于請(qǐng)求中

      反正不是后臺(tái)還在請(qǐng)求,這個(gè)放心,只要把鼠標(biāo)在按鈕和瀏覽上面來(lái)回移動(dòng)幾下就沒了,可能是JQuery UI 的問(wèn)題。FF和Chrom下沒這個(gè)問(wèn)題,就是顯示效果會(huì)有點(diǎn)差,但是上傳沒問(wèn)題的。

      源代碼下載:UploadFileDemo.rar

    【通過(guò)Asp.Net的服務(wù)器控件上傳文件總結(jié)】相關(guān)文章:

    限制文件下載時(shí)上傳速度10-22

    ASP的chr(0)文件上傳漏洞原理及解決方案05-21

    美國(guó)研究生留學(xué)網(wǎng)申上傳文件類型09-05

    ACCA注冊(cè)需要上傳的資料10-04

    asp.net的學(xué)習(xí)過(guò)程講解07-11

    ASP.NET MVC異常處理模塊簡(jiǎn)單教程-ASP.NET教程實(shí)例推薦07-19

    ASP.NET Page函數(shù)調(diào)用解析10-01

    監(jiān)理文件資料的類型-監(jiān)理文件資料分類10-22

    什么是DOS文件07-21

    如何使用ftp工具上傳網(wǎng)站內(nèi)容?07-27

    主站蜘蛛池模板: 国产精品免费看久久久香蕉| 99久久精品国产综合一区| 2020亚洲男人天堂精品| 久久精品国产欧美日韩| 日本精品一区二区三区在线观看| 亚洲高清国产AV拍精品青青草原| 久草欧美精品在线观看| 97久久精品人人做人人爽| 97精品国产福利一区二区三区 | 国产欧美日韩精品丝袜高跟鞋 | 97热久久免费频精品99| 亚洲国产精品无码AAA片| 久久93精品国产91久久综合| 99久久亚洲综合精品成人| 久久精品人人做人人爽电影| 国产精品污WWW在线观看| 亚洲国产精品18久久久久久| 欧美午夜精品久久久久久浪潮| 国产精品主播一区二区| 国产成人AV无码精品| 九九精品在线观看| 国产精品999| 国产精品网站在线观看| 99久久99这里只有免费的精品| 国精品无码一区二区三区在线| 久久丫精品国产亚洲av不卡| 亚洲国产精品va在线播放| 无码人妻精品一区二区三区久久久| 亚洲国产美女精品久久久久∴| 亚洲精品成人区在线观看| 亚洲AⅤ永久无码精品AA| 色国产精品一区在线观看| 3D动漫精品啪啪一区二区下载| 亚洲精品国产美女久久久| 亚洲一区爱区精品无码| 亚洲国产美女精品久久久久∴| 亚洲AV永久无码精品| 日产精品久久久久久久| 99在线精品一区二区三区| 2048亚洲精品国产| 精品国产亚洲一区二区三区|