1. 程式人生 > >記錄小文件上傳的幾個例子(含進度條效果,附源碼下載)

記錄小文件上傳的幾個例子(含進度條效果,附源碼下載)

clas 運行 open ntb httppost 會有 text recent mappath

1、簡單原生上傳

  • 無javascript腳本、無進度條;
  • 借助iframe實現post提交後的無刷新效果;
  • jquery插件ajaxFileUpload.js的實現原型。

Html代碼

    <form enctype="multipart/form-data" action="UploadFile_1" method="post" target="frameResult">
        <div class="item">
            <input id="File1" name="UserPhoto" type="file"
value="" /> <input type="submit" value="提交上傳" /> <iframe src="about:blank" id="frameResult" name="frameResult"></iframe> </div> </form>

後臺代碼(ASP.NET MVC)

        [HttpPost]
        public ActionResult UploadFile_1()
        {
            
string result = "上傳成功"; HttpPostedFileBase file= Request.Files["UserPhoto"]; file.SaveAs(Server.MapPath("~/Upload/")+ file.FileName); return Content(result); }

要點說明

  • 為<form>標簽的action、method設值,以POST方式請求UploadFile_1方法;
  • 為<form>標簽的enctype屬性設值multipart/form-data,讓POST請求帶上<input type="file">的文件內容;
  • 為<form>標簽的target屬性設值frameResult,讓表單的請求響應結果放到名為frameResult的iframe中顯示。

2、純JavaScript異步上傳

  • 借助HTML5特性實現進度條、上傳速度計算;
  • 無需<form>標簽;
  • 不支持IE8、IE9等低版本瀏覽器。

JavaScript代碼,因為不需要<form>標簽,html也沒什麽內容可貼的了。

    var btnUpload = document.getElementById(‘btnUpload‘);
    btnUpload.onclick = function () {
        var fileInput = document.getElementById(‘File2‘);
        if (!fileInput.value) { return; }

        var feature = {};

        feature.fileapi = fileInput.files !== undefined;
        feature.formdata = (typeof window.FormData !== ‘undefined‘);

        if (!feature.fileapi || !feature.formdata) {
            showMessage(‘當前瀏覽器不支持Html5,請更換高級瀏覽器‘);
            return;
        }

        var xhr = new XMLHttpRequest();
        var formData = new FormData();
        formData.append("UserPhoto", fileInput.files[0]);
        xhr.open("post", ‘./UploadFile_2‘);

        //超時時間,單位是毫秒
        xhr.timeout = 60 * 1000;

        //請求結束
        xhr.onload = function (event) {
            if (xhr.status == 200) {
                showMessage("上傳成功");
                return;
            }

            if (xhr.status == 404) {
                showMessage("請求路徑錯誤");
                setProgressBar(0, ‘kb/s‘, ‘hide‘, ‘0%‘);
                return;
            }

            if (xhr.status == 500) {
                console.error(‘xhr.status == 500‘);
                showMessage("服務器異常");
            }
        };

        //請求異常(不包括404)
        xhr.onerror = function () {
            console.error(‘xhr.onerror‘);
            showMessage("請求發生異常");
        };

        //上傳開始事件
        xhr.upload.onloadstart = function () {
            setProgressBar(0, ‘kb/s‘, ‘hide‘, ‘0%‘);
            lastTime = new Date().getTime();
            loadSize = 0;
        }

        //上傳過程事件,間歇調用該方法用來獲取上傳過程中的信息
        xhr.upload.onprogress = function (event) {
            //ProgressEvent.lengthComputable:boolean類型,表示能否計算出文件長度;如果為false,那麽ProgressEvent.total則為0.
            //簡而言之,lengthComputabl等於true就可以做進度計算
            if (!event.lengthComputable) {
                return;
            }

            //計算上傳速度,event.loaded是已發送的大小
            var now = new Date().getTime();
            var timeInterval = (now - lastTime) / 1000;
            lastTime = now;

            var sizeInterval = event.loaded - loadSize;
            loadSize = event.loaded;

            var speed = sizeInterval / timeInterval; // 單位b/s
            var bspeed = speed;
            var units = "b/s";

            if (speed / 1024 > 1) {
                speed = speed / 1024;
                units = ‘kb/s‘;
            }
            if (speed / 1024 > 1) {
                speed = speed / 1024;
                units = ‘mb/s‘;
            }

            speed = speed.toFixed(1);

            //計算剩余時間
            var resttime = ((event.total - event.loaded) / bspeed).toFixed(1); //單位 秒

            //計算進度百分比
            var precent = (100 * event.loaded / event.total);
            pre = Math.floor(precent);

            if (bspeed == 0) {
                //setProgressBar方法是控制進度條的,
                //這裏代碼沒貼,在最後源碼下載裏有
                //四個參數:上傳速度、單位、剩余時間、進度百分比
                setProgressBar(0, "b/s", ‘infinity‘, ‘noChange‘);
            } else {
                setProgressBar(speed, units, resttime, precent + ‘%‘);
            }
        };

        //上傳終止
        xhr.upload.onabort = function () {
            console.info(‘xhr.upload.onabort‘);
        }

        //上傳異常事件
        //當網絡環境正常時,XMLHttpRequest.status等於404、500並不能觸發upload.onerror事件
        //當網絡環境異常時(offline),會觸發upload.onerror事件
        xhr.upload.onerror = function () {
            console.error(‘xhr.upload.onerror‘);
        }

        //文件發送完畢事件
        //當網絡環境正常時,即使XMLHttpRequest.status等於404、500,仍會被觸發upload.onload事件
        //當網絡環境異常時(offline),不會觸發upload.onload事件
        xhr.upload.onload = function () {
            console.info(‘xhr.upload.onload‘);
        }

        //上傳超時
        xhr.upload.ontimeout = function () {
            console.error(‘xhr.upload.ontimeout‘);
        }

        //發送請求
        xhr.send(formData);
    }

後臺接收代碼

        [HttpPost]
        public ActionResult UploadFile_2()
        {
            HttpPostedFileBase file = Request.Files["UserPhoto"];
            file.SaveAs(Server.MapPath("~/Upload/") + file.FileName);
            return Json("success");
        }

要點說明

  • 無需 <form> 標簽
  • 通過判斷document.getElementById(‘File2‘).files 及 window.FormData 對象是否為 undefined ,得出當前瀏覽器是否具備我們所需的HTML5特性;
  • FormData對象如同其名稱一樣以鍵值對形式存儲表單數據;
  • 主要借助 xhr.upload 對象的兩個事件 onloadstart、onprogress 實現進度條。

3、JQuery異步上傳

  • 上個例子的Jquery版;
  • 同樣需要HTML5特性支持,無法在低版本瀏覽器使用。
    $(‘#btnUpload3‘).click(function () {
        var $fileInput = $(‘#File3‘);
        if (!$fileInput.val()) { return; }

        var feature = {};
        //檢查是否支持html5 api
        feature.fileapi = $fileInput.get(0).files !== undefined;
        feature.formdata = (typeof window.FormData !== ‘undefined‘);

        if (!feature.fileapi || !feature.formdata) {
            showMessage(‘當前瀏覽器不支持Html5,請更換高級瀏覽器‘);
            return;
        }

        var formData = new FormData();
        formData.append("UserPhoto", $fileInput[0].files[0]);
        $.ajax({
            type: ‘post‘,
            url: ‘./UploadFile_2‘,
            data: formData,
            processData: false,//設置為false。因為data值是FormData對象,不需要對數據做處理。
            contentType: false, //設置為false。告訴jQuery不要去設置Content-Type請求頭
            xhr: function () {
                var xhr = $.ajaxSettings.xhr();

                if (xhr.upload) {
                    xhr.upload.onloadstart = uploadStart;
                    xhr.upload.onprogress = uploadProgress;
                    return xhr;
                }
            },
            success: function (data, textStatus, jqXHR) {
                showMessage("上傳成功");
            },
            error: function (jqXHR, textStatus, errorThrown) {
                showMessage("上傳失敗");
            }
        });
    });

要點說明

  • processData、contentType 設置為 false;
  • $.ajax()方法中需要為請求設置xhr賦值一個function,用於加工$.ajax()的XmlHttpRequest對象,為xhr.upload 對象的兩個事件 onloadstart、onprogress 綁定處理方法,處理方法同例子2一樣。最後的源碼下載中會有。


4、異步表單插件jquery.form.js

  • 前三個例子的集成版,需要 <form> 標簽做兼容;
  • 當瀏覽器不支持H5,使用例子1的方式;
  • 當瀏覽器支持H5,使用例子2、3的方式。

html代碼

    <form id="form4" enctype="multipart/form-data" action="UploadFile_2" method="post">
        <div class="item">
            <h3>
                4、異步表單插件jquery.form.js
            </h3>

            <input id="File4" name="UserPhoto" type="file" value="" />
            <input id="btnUpload4" type="button" value="提交上傳" />
        </div>
    </form>

js代碼

    $(‘#btnUpload4‘).click(function () {
        var $fileInput = $(‘#File4‘);
        if (!$fileInput.val()) { return; }

        var options = {
            type: ‘post‘,
            url: ‘./UploadFile_2‘,
            success: function (data, textStatus, jqXHR) {
                showMessage("上傳成功");
            },
            error: function (jqXHR, textStatus, errorThrown) {
                showMessage("上傳失敗");
            }
        }

        var feature = {};

        //檢查是否支持html5 api
        feature.fileapi = $fileInput.get(0).files !== undefined;
        feature.formdata = (typeof window.FormData !== ‘undefined‘);

        //如果支持html5,那麽就使用進度條
        if (feature.fileapi && feature.formdata) {
            options = $.extend(options, {
                xhr: function () {
                    var xhr = $.ajaxSettings.xhr();

                    if (xhr.upload) {
                        xhr.upload.onloadstart = uploadStart;
                        xhr.upload.onprogress = uploadProgress;
                        return xhr;
                    }
                }
            });
        }

        $("#form4").ajaxSubmit(options);
    });

要點說明

  • jquery.form.js 仍然需要<form>標簽作為兼容基礎;
  • ajaxSubmit(options)方法中的options參數與$.ajax(options)的參數其實是同一個對象,本質就是 ajaxSubmit為 $.ajax 批了一件外套;
  • 根據上一點,我們可以使用例子3中同樣的手段實現進度條。

源碼下載:https://pan.baidu.com/s/1eWiOzvio9EVW2WlYeaKUGA

代碼是用VS2015 ASP.NET MVC5寫的,我把bin目錄內的dll都刪了,通過還原 nuget 程序包應該就能運行了。

記錄小文件上傳的幾個例子(含進度條效果,附源碼下載)