欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Asp.Net 無刷新文件上傳并顯示進(jìn)度條的實(shí)現(xiàn)方法及思路

 更新時(shí)間:2013年06月28日 16:16:29   作者:  
這篇文章詳細(xì)介紹了無刷新文件上傳并顯示進(jìn)度條的思路和代碼,有需要的朋友可以參考一下

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

效果圖:

本文涉及到的知識(shí)點(diǎn):
1.前臺(tái)用到Html,Ajax,JQuery,JQuery UI

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

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

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

<link href="Styles/jquery-ui-1.8.16.custom.css" rel="stylesheet" type="text/css" />
    <script src="Scripts/jquery-1.6.2.min.js" type="text/javascript"></script>
    <script src="Scripts/jquery-ui-1.8.16.custom.min.js" type="text/javascript"></script>

2、關(guān)于無刷新文件上傳

通過Ajax是不能上傳文件的,無刷新上傳是靠隱藏的iframe來實(shí)現(xiàn)的

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

<form id="form" target = "frameFileUpload" enctype="multipart/form-data">
<div id="progressBar" style="font-size: 1em;"></div>
<input type="file" id="fileUpload" name="fileUpload" /><span id="progressValue"></span>
<iframe id="frameFileUpload" name="frameFileUpload" style="display:none;" ></iframe>
<br />
<input type="submit" value="上傳" id = "submit"/>
</form>

要將form標(biāo)簽的target屬性設(shè)置為iframe的id,當(dāng)然別忘了將form的enctype設(shè)置為multipart/form-data
復(fù)制代碼 代碼如下:

<div id="progressBar" style="font-size: 1em;"></div>

是用來顯示上傳文件時(shí)的進(jìn)度條

在JS中加入如下處理:

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

    <script type="text/javascript">
        $(function () {
            $("#submit").button();
            $("#fileUpload").button();
        });
    </script>

此時(shí)效果:

二、實(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;
            //獲取上傳文件流的總長度
            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ù)制代碼 代碼如下:

<form action="UploadFileHandler.ashx" method="post" id="form" target = "frameFileUpload" enctype="multipart/form-data">

這樣文件上傳就完成了。

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

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

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

  首先客戶端同時(shí)(幾乎是)發(fā)出兩個(gè)請求,一個(gè)是文件上傳,一個(gè)是進(jìn)度請求。由于"處理請求進(jìn)度的程序"是異步處理的,當(dāng)該程序沒有信息發(fā)給客戶 端時(shí),我們讓它處于等待狀態(tài),這里有點(diǎn)像Tcp,這樣客戶端跟服務(wù)器就一直處于連接狀態(tài)。當(dāng)"處理文件上傳的程序"開始處理時(shí),通過把進(jìn)度值賦值給"處理 請求進(jìn)度程序"的異步操作的狀態(tài),并觸發(fā)"處理請求進(jìn)度的程序"返回值給客戶端??蛻舳双@取進(jìn)度值,并處理。這樣一次請求進(jìn)度值的請求就結(jié)束了,我們知道 服務(wù)器是不會(huì)主動(dòng)給客戶端發(fā)送信息的,只有客戶端請求,服務(wù)器才會(huì)響應(yīng)。顯然,要想在文件保存的過程中向客戶端發(fā)送進(jìn)度信息,客戶端得到每得到一個(gè)返回結(jié) 果,都是一次請求。為了得到連續(xù)的請求值,客戶端再向"處理請求進(jìn)度的程序"發(fā)出請求,依次循環(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)該處理程序處理請求 時(shí),BeginProcessRequest是第一個(gè)被調(diào)用的函數(shù),返回一個(gè)包含異步狀態(tài)信息的對象,該對象是IAsyncResult類型,是實(shí)現(xiàn)異步 的關(guān)鍵,用于控制什么時(shí)候調(diào)用EndProcessRequest來結(jié)束處理程序的等待狀態(tài),BeginProcessRequest被調(diào)用之后,程序就 處于等待狀態(tài)。EndProcessRequest是在結(jié)束請求時(shí)的處理函數(shù),通過該函數(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;
        /// <summary>
        /// 獲取或設(shè)置保存下載文件的百分比數(shù)值部分
        /// </summary>
        public long PercentNumber;

        public AsyncResult(HttpContext context, AsyncCallback callback)
        {
            this.context = context;
            this.callback = callback;
        }
        /// <summary>
        /// 向客戶端寫入信息
        /// </summary>
        public void Send()
        {
            this.context.Response.Write(PercentNumber);
        }
        /// <summary>
        /// 完成異步處理,結(jié)束請求
        /// </summary>
        public void DoCompleteTask()
        {
            if (callback != null)
                callback(this);//會(huì)觸發(fā)處理程序中的EndProcessRequest函數(shù),結(jié)束請求
            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
    {
        /// <summary>
        /// 保存異步處理狀態(tài)信息的集合
        /// </summary>
        public static List<AsyncResult> AsyncResults = new List<AsyncResult>();
        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)楸咎幚沓绦蚝?處理請求進(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,則重新請求
                    if (data != 100) {
                        RequestProgress();
                    }
                }
            });
        }

在form中添加事件omsubmit的處理函數(shù)為RequestProgress
復(fù)制代碼 代碼如下:

<form action="UploadFileHandler.ashx" onsubmit = "RequestProgress();" method="post" id="form" target = "frameFileUpload" enctype="multipart/form-data">

補(bǔ)充幾點(diǎn):
1.默認(rèn)Asp.Net允許的上傳文件的大小是4M,可以在Web.config中修改其大小限制
復(fù)制代碼 代碼如下:

    <system.web>
        <httpRuntime maxRequestLength="444444"/>
    </system.web>

maxRequestLength的單位是KB

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

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

源代碼下載:UploadFileDemo.rar

相關(guān)文章

  • 你應(yīng)該知道的.NET錯(cuò)誤與異常處理機(jī)制

    你應(yīng)該知道的.NET錯(cuò)誤與異常處理機(jī)制

    這篇文章主要給大家介紹了關(guān)于.NET錯(cuò)誤與異常處理機(jī)制的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用.NET具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • ASP.NET實(shí)現(xiàn)上傳圖片并生成縮略圖的方法

    ASP.NET實(shí)現(xiàn)上傳圖片并生成縮略圖的方法

    這篇文章主要介紹了ASP.NET實(shí)現(xiàn)上傳圖片并生成縮略圖的方法,提供了一個(gè)asp.net上傳圖片與生成縮略圖的方法,并給出了改進(jìn)程序供大家對比分析,需要的朋友可以參考下
    2015-12-12
  • NET?NativeAOT?用法指南

    NET?NativeAOT?用法指南

    NativeAOT?是?.NET?中一個(gè)非常棒和強(qiáng)大的工具,有了?NativeAOT,你可以以可預(yù)測的性能構(gòu)建你的應(yīng)用,同時(shí)節(jié)省資源(更低的內(nèi)存占用和更小的二進(jìn)制大小),本文介紹NET?NativeAOT?指南,感興趣的朋友一起看看吧
    2024-02-02
  • .NET Core單文件發(fā)布靜態(tài)編譯AOT CoreRT的方法詳解

    .NET Core單文件發(fā)布靜態(tài)編譯AOT CoreRT的方法詳解

    這篇文章主要給大家介紹了關(guān)于.NET Core單文件發(fā)布靜態(tài)編譯AOT CoreRT的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-07-07
  • jQuery+Asp.Net實(shí)現(xiàn)省市二級聯(lián)動(dòng)功能的方法

    jQuery+Asp.Net實(shí)現(xiàn)省市二級聯(lián)動(dòng)功能的方法

    這篇文章主要介紹了jQuery+Asp.Net實(shí)現(xiàn)省市二級聯(lián)動(dòng)功能的方法,涉及asp.net數(shù)據(jù)庫讀取與字符串轉(zhuǎn)換相關(guān)操作技巧,需要的朋友可以參考下
    2017-05-05
  • asp.net(C#)跨域及跨域?qū)慍ookie問題

    asp.net(C#)跨域及跨域?qū)慍ookie問題

    在網(wǎng)站www.A.com下通過iframe或ajax調(diào)用www.B.com下的內(nèi)容時(shí),默認(rèn)情況下IE會(huì)阻止www.B.com寫任何Cookie
    2011-10-10
  • ASP.NET實(shí)現(xiàn)文件上傳功能

    ASP.NET實(shí)現(xiàn)文件上傳功能

    這篇文章主要為大家詳細(xì)介紹了ASP.NET實(shí)現(xiàn)文件上傳功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-07-07
  • ASP.NET中獲取URL重寫前的原始地址詳解

    ASP.NET中獲取URL重寫前的原始地址詳解

    在ASP.NET中,如果你使用了URL重寫,通過HttpContext.Request獲取到的是重寫后的地址。如果這個(gè)地址要返回給客戶端(比如Redirect),我們一般希望是重寫前的友好地址。
    2013-07-07
  • JAVA正則表達(dá)式 Pattern和Matcher

    JAVA正則表達(dá)式 Pattern和Matcher

    java.util.regex是一個(gè)用正則表達(dá)式所訂制的模式來對字符串進(jìn)行匹配工作的類庫包。
    2009-04-04
  • ASP.NET Core與NLog集成的完整步驟

    ASP.NET Core與NLog集成的完整步驟

    NLog是一個(gè)免費(fèi)的日志記錄框架,專門為.net平臺(tái)下的框架提供日志功能,下面這篇文章主要給大家介紹了關(guān)于ASP.NET Core與NLog集成的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2018-07-07

最新評論