Layui上传系列之二(多文件分块上传优化实现)

22 篇文章 0 订阅
9 篇文章 0 订阅

接下来,就要实现layui的uploader分块上传了,在官网上没有提到分块上传,倒是有一个多文件选择后,显示文件列表的例子。

 目录

现状分析

我的做法

功能优化

上代码了

现状分析

对于我们能有啥启发呢,其实主要就是使用了choose事件,然后有个preview方法,可以针对每个文件进行处理(如图片文件预览)

问了下度娘,网上也有layui分块上传的例子,基本原理就是在上述preview方法中,对单个文件进行分块,多次调用上传,即可实现分块上传。

但是网上的例子有个问题就是:只能是单个文件分块上传,多个文件是不支持的。不过在了解清楚他的思路以后,多文件分块上传也是可以做的。

分块上传的基本思路:把一个大文件按照一个标准,对文件流分隔,分别调用上传,最后一片调用完后,返回上传完成,后续不再调用上传。

网上的例子,之所以只能单个文件分块上传,是因为对于上传状态的标识存储到了页面的hidden控件,那么我要实现多文件分块上传,那么我让每个文件都有一个自己的上传状态存储就可以了。

我的做法

在choose方法中,循环files,动态创建tr行,在每行存储一个上传状态的hidden,每次调用完上传后也是通过相应规则去检查返回的上传状态就行了。

这里还有个问题,preview方法在文件比较大的情况下,可能上传无反应,这个度娘也跟我说了,所以就直接遍历files就好了,不过对于已经上传过的文件,需要自己做下处理。

这里的一个改动,又引起了一个新的问题,就是之前调用preview方法的时候,用了一个定时器interval,用于定时调用上传接口,在上传完成后清理掉定时器。之前是单文件分块上传,所以定义一个定时器即可,当我是多文件分块上传的时候,就需要可以动态定义多个定时器了,于是使用了eval方法。就是先根据一个规则,动态定义一个不同名字的定时器,不过脚本是写成字符串,然后再eval执行。

var xx = 'var progressTimer' + f + ' = setInterval(function () {\
                            uploadxx(data, obj, file, LENGTH, fileId, fileName, index,progressTimer'+ f + ')\
                        }, 100);';
eval(xx);

一开始uploadxx方法其实是upload,但是发现调用没反应,估计是和layui自己的upload方法冲突了,改下方法名就行了。

功能优化

基本功能具备后,还要考虑实际应用。

怎么说呢,上传文件,我需要显示上传进度,上传完成后,我还需要绑定一个文件列表(业务),于是决定,选择文件后,弹出层显示上传进度相关内容,点击完成关闭弹出层,再绑定业务的文件列表。

上代码了

var uploadInstNew = upload.render({
                elem: '#chunkUploadNew' //绑定元素
                , elemList: $('#fileList1') //列表元素对象
                , url: '<%=AppPath%>/Sys/Handler/FileUploadHandler.ashx?action=Upload' //上传接口
                , accept: 'file'
                , auto: false
                , multiple: true
                //, size: 100 * 1024
                , choose: function (obj) {
                    var that = this;
                    var data = this.data;
                    var files = obj.pushFile();
                    var LENGTH = 1024 * 1024; //每片文件大小1mb
                    var f = 0;


                    var layer = layui.layer;
                    layer.open({
                        type: 1,
                        title: '文件上传',
                        content: $('#fileUploadList1'),
                        area: ['900px', '350px'],
                        btnAlign: 'c',
                        maxmin: true,
                        closeBtn: 0,
                        moveOut: true,
                        btn: ['完成'],
                        yes: function (index, layero) {
                            layer.close(index);
                        },
                        end: function () {

                        },
                    });

                    for (var key in files) {
                        var file = files[key];
                        var index = key;

                        //已经上传过的文件跳过
                        var tr = that.elemList.find('tr#upload-' + index);
                        if (tr.length > 0) {
                            continue;
                        }

                        f++;
                        var fileId = newGuid();
                        //alert(index);
                        var totalSize = file.size;
                        var totalPage = Math.ceil(totalSize / LENGTH);

                        var tr = $(['<tr id="upload-' + index + '">'
                            , '<td>' + file.name + '</td>'
                            , '<td>' + (file.size / 1014).toFixed(1) + 'kb</td>'
                            , '<td>'
                            , '<div class="layui-progress"  lay-showpercent="true" lay-filter="progress-demo-' + index + '"><div class="layui-progress-bar" lay-percent=""></div></div>',
                            , '<input type="hidden" id="totalPage" value="0" />'
                            , '<input type="hidden" id="page" value="1" />'
                            , '<input type="hidden" id="status" value="0" />'
                            , '</td>'
                            , '<td>'
                            , '<button class="layui-btn layui-btn-xs demo-reload layui-hide">重传</button>'
                            , '<button class="layui-btn layui-btn-xs layui-btn-danger demo-delete">删除</button>'
                            , '</td>'
                            , '</tr>'].join(''));

                        //单个重传
                        tr.find('.demo-reload').on('click', function () {
                            obj.upload(index, file);
                        });

                        //删除
                        tr.find('.demo-delete').on('click', function () {
                            delete files[index]; //删除对应的文件
                            tr.remove();
                            uploadListIns.config.elem.next()[0].value = ''; //清空 input file 值,以免删除后出现同名文件不可选
                        });

                        tr.find('#totalPage').val(totalPage);
                        tr.find('#page').val('1');
                        //默认-1分块上传
                        tr.find('#status').val('-1');

                        that.elemList.append(tr);

                        //只初始化当前进度条,避免将之前100%重新初始化了
                        element.render('progress', 'progress-demo-' + index); //渲染新加的进度条组件

                        var fileName = file.name;
                        fileName = fileName.substr(0, fileName.lastIndexOf('.'));

                        preview(f, data, obj, file, LENGTH, fileId, fileName, index, that);
                    }

                    //如下方法,对于大文件(100多兆)的情况可能无响应
                    //obj.preview(function (index, file, result) {
                    //});
                }
                , done: function (res, index, upload) {

                    var that = this;

                    var tr = that.elemList.find('tr#upload-' + index)
                        , tds = tr.children();


                    if (res.code == '-1') { //分片上传

                        //if(res.code == 0){ //上传成功
                        var pageStr = that.elemList.find('tr#upload-' + index + ' #page').val();
                        var page = parseInt(pageStr);

                        var totalPageStr = that.elemList.find('tr#upload-' + index + ' #totalPage').val();
                        var totalPage = parseInt(totalPageStr);

                        element.progress('progress-demo-' + index, Math.ceil(page * 100 / totalPage) + '%'); //执行进度条。n 即为返回的进度百分比

                        page = page + 1;
                        console.log(page);
                        that.elemList.find('tr#upload-' + index + ' #page').val(page);
                        that.elemList.find('tr#upload-' + index + ' #status').val('-1');
                    }
                    else if (res.code == '0') { //上传完成
                        element.progress('progress-demo-' + index, '100%'); //执行进度条。n 即为返回的进度百分比
                        that.elemList.find('tr#upload-' + index + ' #status').val('0');

                        tds.eq(3).html(''); //清空操作
                        //delete this.files[index]; //删除文件队列已经上传成功的文件
                        return;
                    }
                    else { //上传错误
                        that.elemList.find('tr#upload-' + index + ' #status').val('1');
                        element.progress('progress-demo-' + index, '0%'); //执行进度条。n 即为返回的进度百分比
                    }
                }
                , allDone: function (obj) { //多文件上传完毕后的状态回调
                    console.log(obj)
                }
                , error: function () {
                    //请求异常回调
                }
            });

//定时执行必须单独设置一个方法,否则会导致只执行最后一个定时
        function preview(f, data, obj, file, LENGTH, fileId, fileName, index, that) {
            var xx = 'var progressTimer' + f + ' = setInterval(function () {\
                            uploadxx(data, obj, file, LENGTH, fileId, fileName, index, progressTimer'+ f + ',that)\
                        }, 100);';
            eval(xx);
        }

        function uploadxx(data, obj, file, len, fileId, fileName, index, progressTimer, that) {
            console.log(index);

            var pageStr = that.elemList.find('tr#upload-' + index + ' #page').val();
            var totalPageStr = that.elemList.find('tr#upload-' + index + ' #totalPage').val();
            var status = that.elemList.find('tr#upload-' + index + ' #status').val();

            var page = parseInt(pageStr);
            var totalPage = parseInt(totalPageStr);

            if (totalPage == page && (parseInt(status) == '0' || parseInt(status) == '1')) {
                clearInterval(progressTimer);

                console.log('clear');
            }
            else {
                if (status == '-1') {
                    that.elemList.find('tr#upload-' + index + ' #status').val('-2');
                    data.fileId = fileId;
                    data.fileName = fileName;
                    data.fileSourceId = '<% =Guid.NewGuid()%>';
                    data.fileSourceFlag = "Form";
                    data.fileType = 'Test';
                    data.page = page;
                    data.totalPage = totalPage;
                    obj.upload(index, file.slice((page - 1) * len, page * len));
                }
            }
        }

这样基本是实现了,不过我还想继续封装下,简化开发。

 Layui上传系列之三(插件封装,简化开发)_龙井茶的Sky-CSDN博客icon-default.png?t=L892https://blog.csdn.net/to_love_/article/details/120660380

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值