zoukankan      html  css  js  c++  java
  • 记录小文件上传的几个例子(含进度条效果,附源码下载)

    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 程序包应该就能运行了。

  • 相关阅读:
    UNIX网络编程(转载)
    cin、cin.get()、cin.getline()、getline()、gets()等函数的用法(转)
    GSL GNU Scientific Library
    为人处事很有意义
    上海老大杜月笙——教你看穿一个人
    超实用的Linux/Unix快捷键大汇总(开发、管理)(2)(转)
    STL map常用操作简介(转)
    使用ifstream和getline读取文件内容[c++]
    VIM Tips
    超实用的Linux/Unix快捷键大汇总(开发、管理)(1)(转)
  • 原文地址:https://www.cnblogs.com/xurongjian/p/9853230.html
Copyright © 2011-2022 走看看