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

2023-05-16

接下来,就要实现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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

  • 每周五条-002

    2020 4月第4周 职场 假如开发人员 耍大牌 xff0c 十有八九是井底之蛙 xff0c 盲目自大 产品 产品不能一直靠人手动维护它正常运作 xff0c 一定要让客户自己有功能来解决实际问题 有些一时找不到原因的异常问题习惯了软件公司自
  • visual svn修改新url地址方法(linux,windows,centos)

    在工作环境调整时 有的时候SVN服务器的地址需要修改 xff0c 此时我们如何修改本地库的地址 xff0c 而不用重新下载呢 xff1f SVN中有一个简单的解决办法 xff1a 1 环境为windows7 在工作复本的根目录上右键 gt
  • 小公司项目经理的一天,记录我普通的一天

    团队5人 xff0c 电子商务Web项目 xff0c 前段时间离职2人 xff0c 尚未补充 xff0c 手下现有一个开发组长 一个程序员 一个美术设计 一个运营专员 xff0c 还算一个完整的战斗单位 直接汇报对象 xff0c 几乎是老总
  • 关于ASP.NET木马ASPXSPY的初步处理研究

    前段时间服务器中了木马了 xff0c 经过排查 xff0c 截获了ASPXSPY木马 该木马是用ASP NET写的 xff0c 为了知己知彼 xff0c 就将木马拷到本地运行研究 xff0c 发现功能真的很强大 xff0c 自认为服务器设置
  • 身于“乱世”,我们程序员应该如何打算?

    不仅要低头拉车 xff0c 还要抬头看路 在周末夜深人静的时候就要思考一下人生 此 乱世 虽非战火纷飞 民不聊生的彼乱世 xff0c 但是整个社会的观感确实让人不得不焦虑 xff1a 不断飞涨的物价 xff0c 让买猪肉鸡蛋都觉得有压力 x
  • 开发人员流失之痛和团队重建之困

    最近笔者正在经历人员流失和团队重建的难题 xff0c 趁周末整理一下思路 xff0c 准备重整旗鼓 今年也算是多事之秋 xff0c 作为公司一员 xff0c 于公于私都有些坐不住了 面对开发人员 xff08 当然其他部门也有辞职 一个一个的
  • 从电影《三傻大闹宝莱坞》看IT新手应如何学习?

    三傻大闹宝莱坞 电视上又在放 xff0c 又看了一遍 xff0c 觉得很赞 很喜剧 很有意义 很励志 追求卓越 xff0c 成功将不穿裤子追着你跑 代替富翁主人儿子去读大学的兰乔在学校干了很多离经叛道的事情 xff0c 由此也产生了许多爆笑
  • 程序员,2012,不再生活在别处

    2011走到了尽头 xff0c 这一年有太多事情值得去书写和记忆 xff1a 浪漫的自行车户外婚礼 xff0c 历尽艰辛迎来了小宝宝 xff0c 整个部门业绩比去年增长了几倍 阳春三月 xff0c 黄道吉日 xff0c 在一群年轻朝气的自行
  • RTX, uCOS-II, FreeRTOS embOS, uCOS-III的综合性能PK

    这5款OS的PK主要分为以下四个方面 1 FLASH和RAM的需求对比 2 功能对比 3 实时性对比 4 安全性对比 1 FLASH和RAM的需求对比 RTX uCOS II FreeRTOS embOS uCOS III FLASH lt
  • 当段子手已经hi起来的时候,产品经理也来瞎逼逼一下faceid

    苹果发布会后 xff0c 各种段子满天飞 xff0c 着实热闹了一把 比较经典的包袱是 xff1a 老婆被老公刷脸 xff1b 被打成熊猫后没法报警 xff1b 韩国人没法用 xff1b 比较正式的疑问是 xff1a 双胞胎怎么办 xff1
  • SQL 2005安装时报已经安装了同名实例的问题解决。(无法正确卸载干净时最管用)

    最近重装SQL2005 xff0c 卸载后报 SQL 2005此计算机上已经安装了同名实例 说明原来的安装没有卸载干净 需要按照如下办法 1 停止服务 停止所有与SQL Server相关的服务 2 清楚残留的安装 使用windows ins
  • .NET Reflector 7.6.1.824安装及破解(刚试了,绝对能用)

    首先下载在这里http download csdn net detail gattaca2011 4578752 xff0c 不要到官网去了 xff0c 因为官网已经是8 0了 然后就是安装 xff0c 运行注册机 xff08 注意断网 x
  • 稍微冷门一点的经验,phpnow不能打开默认页的问题处理

    因为本地调试项目需要 xff0c 需要使用 phpnow 下载安装都很简单 xff0c 可是安装后127 0 0 1显示不出默认页 xff0c 而且一直处于加载状态 尝试 开始以后是一个网卡绑定了多个IP的问题 xff0c 于是移除多个IP
  • 每周五条-001

    2019 第2周 忙碌而焦虑 1 微信 微信支付服务商帐号是不能收款的 xff0c 如果同一个公司已经是服务商 xff0c 也不能在该服务商下创建本身的普通商户号 解决办法直接申请普通商户号 2 微信 听了两天的公开课 xff0c 最大的感
  • OpenWrt 学习笔记【1】LEDE17 安装huawei E8372

    写在前面的话 xff1a 路由器本身刷了LEDE后只是作为千兆交换机和手机wifi共享器 家中光线猫位置尴尬 xff0c 被关在入户的接线盒里 xff0c 信号差的一塌糊涂 xff0c 本来只是在luci界面直接尝试路由器自身2 4Gwif
  • Python3.6.2 pip install 报 【Fatal error in launcher: Unable to create process using ' " ' 】

    win10pro 原来的同事装了3 6 x xff0c 但是啥库都没安 xff0c 另一台自己的电脑原先安过需要的库 xff08 如h5py xff0c tf xff0c mkl等等 xff09 直接一波操作打压缩包拷过去解压覆盖 xff0
  • Keras2.2.2离线安装依赖包依赖Keras2.1.6解决方法。

    离线使用pip install 本地的whl包 xff0c 结果发现keras2 2 2安装失败 xff0c 照着提示依赖找到了Keras Applications 1 0 4与Keras Preprocessing 1 0 2 xff0c
  • 系统时间【linux基础】

    基础tip 备忘 who命令 1 xff09 who b 查看最后一次系统启动的时间 xxxxx 64 XXXXX who b system boot 2019 02 10 20 15 2 xff09 who r 查看当前系统运行时间 xx
  • TF踩坑笔记

    遇到领导要求出demo xff0c 尬 xff0c 好久没撸ML了 xff0c 工作两年信息流打杂 xff0c 以前也就叶公好龙毕业前VS编译了一波caffe跑了几个demo xff0c 尬出天际 xff0c 这两天踩坑不少 xff0c 留
  • MDK Trace功能

    RealView MDK可以轻松实现TRACE功能 针对ARM Cortex M3内核的芯片 xff0c 只需要要RealView MDK软件和ULINK2仿真器就可以直接实现TRACE功能 xff0c 不需要额外的TRACE硬件仿真器支持

随机推荐

  • 史上最快速的安装Tensorflow方法

    pip install i https pypi tuna tsinghua edu cn simple tensorflow 这里修改成自己需要安装的框架
  • 软件工程师面试经典问题

    大部分内容来自 高质量C 43 43 C 编程指南 和 嵌入式程序员应知道的0x10个问题 的补充整理 1 如何避免重复包含头文件 xff1f 答 xff1a 使用 ifndef define endif 2 include lt file
  • ubuntu18.04安装Realsense D435i 摄像头的SDK和ROS Wrapper

    1 安装参考链接 2 报错链接 3 没有找到rgbd launch 无法定位软件包
  • 写论文感悟

    无论最终结果怎么样 xff0c 这段过程值得纪念 xff0c 经常上的学术论坛是小木虫 xff0c 主要关注的版面是 xff1a 学术交流区 文献求助区 硕博家园 1 文献阅读和管理经验 xff0c 见 xff1a http muchong
  • ubuntu下python版本如何切换

    添加版本python版本管理 shell里执行 xff1a sudo update alternatives install usr bin python python usr bin python2 100 sudo update alt
  • Python函数的参数传递以及是否会改变外部变量的值

    这个问题是由听课时的例子引出的 xff1a 二分查找的递归实现 xff0c 以下是烂代码 xff1a 除去递归实现 xff0c 代码中参数传递的错误一言难尽 Python参数传递 1 如果没有将外部变量传递到函数中 xff0c 函数内部可以
  • OpenLTE开源代码结构解析(一)

    跟踪了一个在将开源组织 OpenLTE xff08 将4G通信网络LTE开源 xff09 xff0c 现将自己梳理整理的一些文档Post出来 xff0c 请有相同兴趣的朋友指点 xff1a 一 xff0c 系统介绍 OpenLTE是一位Mo
  • OpenLTE开源代码结构解析(二)

    对eNodeB的一些配置以及代码结构进行说明 xff0c 如下 xff1a 一 xff0c eNodeB配置结构 控制进程 xff08 传递eNB配置命令 xff09 eNB按照配置进程的配置命令工作 1 xff0c 在一个Tab窗口运行L
  • java.sql.SQLException: ORA-28000: the account is locked

    java sql SQLException ORA 28000 the account is locked 原创 2017年04月25日 17 25 10 标签 xff1a oracle 密码 958 1 现象 xff1a 项目启动时报了
  • 程序猿就是用来改变世界的

    先来一个自我介绍 xff0c 我是一个大三的老学姐 xff0c 专业是软件工程 说真的 xff0c 高考完当我知道我的录取专业是软件工程 xff0c 我一脸懵 xff0c 我什么时候填了这个专业 但是我现在想告诉你 xff0c 这是一个很神
  • DMA周期挪用(cycle-steal)

    周期挪用是指利用CPU不访问 存储器的那些周期来实现DMA操作 xff0c 此时DMA可以使用总线而不用通知CPU也不会妨碍CPU的工作 周期挪用并不减慢CPU的操作 xff0c 但可能需要复杂的时序电路 xff0c 而且 数据传送过程是不
  • 【软件笔记------Orcad Capture CIS 17.2/pads vx2.7】------ orcad&pads PCB设计简要教程

    目录 一 Orcad原理图库1 库添加1 1 新建库1 2 添加库 2 库编辑2 1 元件添加2 2 多PART元件添加2 3属性编辑 3 注意事项 二 原理图1 快捷键2 快捷图标3 选择过滤器4 插入图片5 栅格6 自动编号7 封装分配
  • 《飞控介绍》

    飞控 xff1a 即为导航飞控系统 xff0c 也叫自驾仪 物体运动的三个轴 xff08 多旋翼 xff09 俯视多旋翼时 xff1a 与中心纵向的轴叫做纵轴 xff08 x轴 xff09 与中心横向的轴叫做横轴 xff08 y轴 xff0
  • docker镜像仓库

    前言 镜像 xff0c 可以理解为将应用程序和运行环境打包成 应用模板 xff0c 是容器的上层抽象 容器是镜像的运行实例 xff0c 启动时传入相应的参数 xff0c 即可运行应用程序 二者的关系类似于代码中的 类和对象 要以容器的方式运
  • 杂谈我的IT梦

    误打误撞进入IT 我个人认为我还有是属于能说会道的 xff0c 比较善于与人沟通 xff0c 表达能力也可以 xff0c 所以当初我准备选的专业是医药营销 xff0c 因为那个时候根据我的分析 xff0c 医药是个很可观的赚钱领域 xff0
  • Ubuntu更新sudo apt update库报错

    sudo apt update报错 evyn 64 ubuntu sudo apt update E 文件 list 第 1 行的记录格式有误 etc apt sources list d ros latest list Suite E 无
  • 孤立森林(Isolation Forest)从原理到实践

    异常检测 离群点是在给定数据集中 xff0c 与其他数据点显著不同的数据点 异常检测是找出数据中离群点 和大多数数据点显著不同的数据点 的过程 离群点 真实世界中的大型数据集的模式可能非常复杂 xff0c 很难通过查看数据就发现其模式 这就
  • 一个C++程序员的学习经历

    正在上网的时候有这个念头的 xff0c 所以急急忙忙找了一些学习编程的高人的感想 xff1a 我开始学VC时就是自己一个人在啃 xff0c 也没什么人指导 xff0c 当时没有条件上网 xff0c 资料特别少 xff0c 在书店里随便买本书
  • Mac mini 2018 win10 外接显卡终极教程

    Mac mini 2018 win10 外接N卡应该算是最简单了 但是有些小问题 xff0c 比如说总是需要插拔雷电3的线材 xff0c 对于强迫症或者偏执来说总是感觉不爽 一种解决方案是用refind 启动方法 xff0c 将refind
  • Layui上传系列之二(多文件分块上传优化实现)

    接下来 xff0c 就要实现layui的uploader分块上传了 xff0c 在官网上没有提到分块上传 xff0c 倒是有一个多文件选择后 xff0c 显示文件列表的例子 目录 现状分析 我的做法 功能优化 上代码了 现状分析 对于我们能