多文件断点续传

前端代码


@{
    ViewBag.Title = "Index";
    <link rel="stylesheet" href="/Content/gdsm/vendor/bootstrap-3.3.7/css/bootstrap.min.css">
    <link rel="stylesheet" href="/Content/gdsm/vendor/bootstrap-datepicker-1.6.4-dist/css/bootstrap-datepicker3.min.css">
    <link rel="stylesheet" href="/Content/gdsm/css/common.css">
    <link rel="stylesheet" href="/Content/gdsm/css/admin.css">
    <script src="/Content/gdsm/vendor/jquery-3.3.1/jquery-3.3.1.min.js"></script>
    <script src="/Content/gdsm/vendor/bootstrap-3.3.7/js/bootstrap.min.js"></script>
    <script src="/Content/gdsm/vendor/layer-v3.1.1/layer/layer.js"></script>
    <script src="/Content/gdsm/vendor/jquery.nicescroll-3.7.6/jquery.nicescroll.min.js"></script>
    <script type="text/javascript" src="~/Content/gdsm/vendor/bootstrap-datepicker-1.6.4-dist/js/bootstrap-datepicker.min.js"></script>
    <script type="text/javascript" src="~/Content/gdsm/vendor/bootstrap-datepicker-1.6.4-dist/locales/bootstrap-datepicker.zh-CN.min.js"></script>
    <script src="/Content/gdsm/js/common.js"></script>
    ViewData["datacategory"] = ViewContext.RouteData.Values["categoryData"];
    string fileType = ViewContext.RouteData.Values["categroy"].ToString();
}
    <div id="addShapeContent">
        <div class="panel">
            <div class="panel-heading">
                <h3 class="panel-title">文件上传</h3>
            </div>
            <div class="panel-body shape-upload p30">
                <div class="upload-box item">
                    @switch (fileType)
                    {
                        case "image":
                            <div class="upload-btn">
                                <input type="file" name="uploadFile" multiple="multiple" accept=".jpg,.jpeg,.png,.gif,.bmp,.tif">
                                选择文件
                            </div>
                            <p class="file-desc">(图片支持jpg, jpeg, png, gif, bmp, tif;大小不超过5M,推荐尺寸:4:3,16:9)</p>
                            break;
                        case "media":
                            <div class="upload-btn">
                                <input type="file" name="uploadFile" multiple="multiple" accept=".mp4,.flv,.avi,.wmv">
                                选择文件
                            </div>
                            <p class="file-desc">(视频支持mp4, flv, wmv, avi;大小不超过20M)</p>
                            break;
                        case "music":
                            <div class="upload-btn">
                                <input type="file" name="uploadFile" multiple="multiple" accept=".mp3">
                                选择文件
                            </div>
                            <p class="file-desc">(音频支持mp3大小不超过20M)</p>
                            break;
                        case "shape":
                            <div class="upload-btn">
                                <input type="file" name="uploadFile" multiple="multiple" accept=".jpg,.jpeg,.png,.gif,.bmp,.tif">
                                选择文件
                            </div>
                            <p class="file-desc">(图片支持jpg, jpeg, png, gif, bmp, tif;大小不超过5M,推荐尺寸:4:3,16:9)</p>
                            break;
                    }

                </div>
                <div class="item">
                    <div class="control-label">添加至</div>
                    <div class="control">
                        <select id="sltcategory" class="form-control">
                            @if (ViewData["datacategory"] != null)
                            {
                                foreach (var item in ViewData["datacategory"] as List<GDSMModel.JHResCategory>)
                                {
                                    <option value="@item.res_category_id">@item.res_category_name</option>
                                }
                            }
                        </select>
                    </div>
                </div>
                <div class="item">
                    <div id="prolabel" class="control-label" style="display:none">正在上传中</div>
                    <div class="control">
                        <ul id="proul" class="progress-lists mt34" style="height:135px; overflow-y:auto;"></ul>
                    </div>
                </div>
            </div>
            <div class="panel-footer">
                <button type="button" class="btn btn-lucency js-cancle pull-right ml20">关闭</button>
            </div>
        </div>
    </div>

    <div id="progressbar" style="display:none">
        <li class="progress-detail" id="****">
            <span class="name" title="####" style="height:30px;">####</span>
            <div class="progress progress-striped active">
                <div class="progress-bar progress-bar-success" role="progressbar"
                     aria-valuenow="60" aria-valuemin="0" aria-valuemax="100"
                     style="width:0%;">
                </div>
            </div>
            <span class="num" style="width:30px;">0%</span>
            <label class="currIndex" style="display:none">0</label>
            <button class="btn btn-blue btn-sm" onclick="PauseAndContinue(this);" style="margin-right:10px">暂停</button>
            <button class="btn btn-blue btn-sm" onclick="Cancle(this);">取消</button>
        </li>
    </div>
    <script type="text/javascript">
        //用于存储file信息
        var filearr = new Array();
        //离线状态下的fileID
        var offlinefileids = new Array();
        $(function () {
            //数组加个删除功能
            Array.prototype.remove = function (val) {
                var index = this.indexOf(val);
                if (index > -1) {
                    this.splice(index, 1);
                }
            };

            //监听网络已连接事件
            window.addEventListener('online', Online);

            //上传功能
            $("input[type='file']").change(function () {
                var filelists = this.files;
                //切换下标签类型,防止上传同一文件OnChange触发不了
                $(this).attr("type", "text");
                $(this).attr("type", "file");
                for (var i = 0; i < filelists.length; i++) {
                    if (filelists == undefined) {
                        layer.open({
                            title: '错误提示'
                            , content: '您的浏览器暂不支持上传文件,建议使用IE9以上、FireFox、Chrome、360极速模式等浏览器。'
                        });
                        return;
                    }
                    if (filelists.length < 1) {
                        layer.open({
                            title: '错误提示'
                            , content: '请选择文件。'
                        });
                        return;
                    }

                    //验证格式类型
                    var fileSplit = filelists[i].name.toLowerCase().split(".");
                    var fileFormat = fileSplit[fileSplit.length - 1]; //获得文件结尾的类型如 zip rar 这种写法确保是最后的
                    if (validate(fileFormat, filelists[i].name)) {
                        $("#prolabel").show();
                        var fileid = uuid();//生成一个文件ID
                        var file = filelists[i];
                        var totalSize = filelists[i].size;//文件大小
                        var blockSize = 1024 * 1024;//块大小
                        var blockCount = Math.ceil(totalSize / blockSize);//总块数
                        //存储file信息
                        var data = new fileData(file, totalSize, blockCount, blockSize);
                        filearr[fileid] = data;
                        //存储执行上传中的文件id
                        offlinefileids.push(fileid);
                        //获取服务器上最近上传的文件块序号
                        //currIndex = 0;

                        //生成进度条
                        var progressbar = $("#progressbar").html();
                        //替换名称
                        progressbar = progressbar.replace(new RegExp("####", 'g'), file.name);
                        //替换ID
                        progressbar = progressbar.replace("****", fileid);
                        $("ul.progress-lists").append(progressbar);
                        //开始分块上传文件
                        UploadPost(fileid, file, totalSize, blockCount, blockSize);
                    }
                }
            });

        });

        //上传文件
        function UploadPost(fileid, file, totalSize, blockCount, blockSize) {
            var queryid = "#" + fileid;
            var state = $(queryid).find("button[style]").html();//获取暂停继续的状态
            var currIndex = parseInt($(queryid).find("label.currIndex").html());//获取文件块数
            var category = $("#sltcategory").val();
            if (!(state == "暂停")) {
                if ($(queryid).find("label.currIndex").html() == "-1") {
                    //取消上传,删除文件块
                    CancleAjax(queryid, fileid);
                }
                return; //暂停
            }
            try {

                var start = currIndex * blockSize;                  //文件流开始位置
                var end = Math.min(totalSize, start + blockSize);   //文件流结束位置
                var block = file.slice(start, end);                 //截取下来的文件流块信息

                //组装提交表单信息
                var formDataBlock = new FormData();
                formDataBlock.append('fileName', file.name);//文件名
                formDataBlock.append('blockCount', blockCount);//总块数
                formDataBlock.append('currIndex', currIndex);//当前上传的块下标
                formDataBlock.append('uploadId', fileid);//上传编号
                formDataBlock.append('fileType', "@fileType");//文件类别
                formDataBlock.append('categoryType', category)//分类
                formDataBlock.append('totalSize', totalSize)//文件大小,用于验证
                formDataBlock.append('data', block);

                //提交服务器
                $.ajax({
                    url: '/Admin/FileUpload/Upload',
                    type: 'post',
                    data: formDataBlock,
                    processData: false,
                    contentType: false,
                    success: function (res) {
                        block = null;
                        if ($(queryid).find("label.currIndex").html() == "-1") {
                            //取消上传,删除文件块
                            CancleAjax(queryid, fileid);
                        }
                        else if (res.Code === 1) {
                            //设置进度条
                            currIndex++;
                            var num = Math.round((currIndex) / blockCount * 100) + "%";
                            $(queryid).find("span.num").html(num);
                            $(queryid).find("div.progress-bar").css("width", num);
                            //如果当前文件块不是最后一个,递归上传其他文件块信息
                            if (currIndex < blockCount) {
                                $(queryid).find("label.currIndex").html(currIndex);
                                UploadPost(fileid, file, totalSize, blockCount, blockSize);
                            }
                            else {
                                //上传成功
                                $(queryid).fadeOut(2000, function () {
                                    $(this).remove();
                                    if ($("#proul").children().length <= 1)
                                        $("#prolabel").fadeOut("fast");
                                });
                                offlinefileids.remove(fileid);
                                filearr[fileid] = "";
                            }
                        }
                        else {
                            layer.open({
                                title: '错误提示'
                                , content: res.Msg
                            });
                        }
                    }, error: function (e) {
                        if (!navigator.onLine) {
                            layer.open({
                                title: '错误提示'
                                , content: '网络连接已断开。'
                            });
                        }
                        else if (e.status == 0) {
                            UploadPost(fileid, file, totalSize, blockCount, blockSize);
                        }
                        else {
                            layer.open({
                                title: '错误提示'
                                , content: e.responseText
                            });
                        }
                    }
                });
            } catch (e) {
                alert(e);
            }
        }
        //暂停
        function PauseAndContinue(obj) {
            var fileid = $(obj).parent().attr("id");
            if ($(obj).html() == "暂停") {
                $(obj).html("继续");
                offlinefileids.remove(fileid);
            }
            else {
                $(obj).html("暂停");
                var fdata = filearr[fileid];
                offlinefileids.push(fileid);
                UploadPost(fileid, fdata.file, fdata.totalSize, fdata.blockCount, fdata.blockSize);
            }
        }
        //取消
        function Cancle(obj) {
            $(obj).parent().find("label.currIndex").html("-1");
        }

        //取消上传,删除文件块
        function CancleAjax(queryid, fileid) {
            $.ajax({
                url: '/Admin/FileUpload/Cancle?id=' + fileid,
                datatype: "json",
                type: "GET",
                async: false,
                success: function () {
                    $(queryid).find("span.num").html("0%");
                    $(queryid).find("div.progress-bar").css("width", 0);
                    $(queryid).fadeOut(2000, function () {
                        $(this).remove();
                        if ($("#proul").children().length <= 1)
                            $("#prolabel").fadeOut("fast");
                    });
                }
            });
        }

        //网络连接上继续执行上传
        function Online() {
            for (var i = 0; i < offlinefileids.length; i++) {
                var fileid = offlinefileids[i];
                var fdata = filearr[fileid];
                UploadPost(fileid, fdata.file, fdata.totalSize, fdata.blockCount, fdata.blockSize);
            }
        }

        //验证
        function validate(fileType,filename)
        {
            var type = "@fileType";
            var result = true;
            switch (type) {
                case "image":
                    if (fileType != "jpg" && fileType != "jpeg" && fileType != "png" && fileType != "gif" && fileType != "bmp" && fileType != "tif" && fileType != "") {
                        layer.open({
                            title: '格式错误'
                            , content: filename + '的格式错误'
                        }); 
                        result = false;
                    }
                    break;
                case "shape":
                    if (fileType != "jpg" && fileType != "jpeg" && fileType != "png" && fileType != "gif" && fileType != "bmp" && fileType != "tif" && fileType != "") {
                        layer.open({
                            title: '格式错误'
                            , content: filename + '的格式错误'
                        });
                        result = false;
                    }
                    break;
                case "music":
                    if (fileType != "mp3") {
                        layer.open({
                            title: '格式错误'
                            , content: filename + '的格式错误'
                        });
                        result = false;
                    }
                    break;
                case "media":
                    if (fileType != "mp4" && fileType != "flv" && fileType != "avi" && fileType != "wmv") {
                        layer.open({
                            title: '格式错误'
                            , content: filename + '的格式错误'
                        });
                        result = false;
                    }
                    break;
            }
            return result;
        }

        //生成GUID
        function uuid() {
            var s = [];
            var hexDigits = "0123456789abcdef";
            for (var i = 0; i < 36; i++) {
                s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
            }
            s[14] = "4";  // bits 12-15 of the time_hi_and_version field to 0010
            s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);  // bits 6-7 of the clock_seq_hi_and_reserved to 01
            s[8] = s[13] = s[18] = s[23] = "-";

            var uuid = s.join("");
            //return uuid;
            return uuid.replace(new RegExp("-", 'g'), "");
        }

        //用于存储file信息
        function fileData(file, totalSize, blockCount, blockSize) {
            this.file = file;
            this.totalSize = totalSize;
            this.blockCount = blockCount;
            this.blockSize = blockSize;
        }
    </script>

相关文章: