侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

tp5+layui实现上传大文件介绍

前端  /  管理员 发布于 5年前   413

首先记录下更改文件上传大小的一些配置信息.

打开php.ini

file_uploads = on     //是否允许通过HTTP上传文件的开关,默认开启

upload_tmp_dir    //临时文件储存的路径

upload_max_filesize 20M //允许上传的文件最大值

post_max_size 22M //通过表单POST所能上传的大小

max_execution_time 600  //单个PHP页面允许运行的最大时间

max_input_time 600 //单个PHP页面接收数据所需的最大时间,默认60秒

memory_limit 256M //单个PHP页面执行过程中可占用的最大内存,默认8M

通过更改上述的配置就可以调整允许文件上传的大小。(有的还需要调整服务器的一些配置)

补充:413错误 如果服务器是nginx的话,需要更改配置nginx_conf 中的client_max_body_size 24M,设置接收客户端发送过来包的最大值。记得放在http里,重启服务器,用restart,不要用reload。

接着开始实现文件的分割上传。

文件通过HTML的input标签的file来选择文件上传。通过H5新对象FileReader。就像字面上的意思一样FileRaeder对象就是一个读取本地文件的对象。FileReader对象可以将本地文件读取后以base64位的编码返回。(具体有关FileReader对象的使用,请自行百度,或者阅读以下博文,写的很具体。

实际开发

第一次尝试

通过input file标签来选择文件

采用FileReader对象对文件进行读取

通过ajax异步将文件的base64编码发送给服务端

服务端接收后对编码进行解码并保存到文件中。

测试结果失败,当文件过大时所编码的长度也越长,通过ajax异步提交参数的最大上线为8000个字节。

第二次尝试

在第一次的基础上对所获取到的base64编码进行分割上传

将所获取的base64编码字符串分成几份并进行编号,在循环调用ajax进行发送

服务端接收到后对数据进行解码,以编号进行命名

接收完所有小文件后,调用后台方法将小文件进行合并

测试结果失败,当上传文件超过1G时,浏览器就崩溃了。应该是在读取文件时,文件过大,一次性读出返回base64编码过大,导致页面崩溃。

第三次尝试

在第二次的基础上想着在读取文件获取编码的过程也进行分批读取来避免一次性读取过大的文件导致页面崩溃。

这边就要使用到H5的file.slice()来对文件进行分块,从而实现分批读取分批上传。

通过FlieReader对象来读取文件快

通过ajax将base64编码异步发送到服务端

服务端接收数据进行解码和文件保存

测试成功,测试上传了快4G的文件。

(由于将文件进行了分段,所以在上传大文件时会发起大量的ajax请求,产生大量的并发,可能会导致页面再次崩溃。所以我才用错开请求的方式。减慢产生ajax请求的速度。)

具体实现代码

接下来贴点代码

前端框架:layui

后端框架:tp5

页面代码:

<div class="layui-form-item">    <label class="layui-form-label">视频上传</label>    <div class="layui-input-block layui-upload-video-btn">        <ul>            <li class="img-upload">                <label></label>                <input type="file" class="video-upload-file layui-upload-video-file-btn" name="file"/>                <video width="320" height="240" controls style="display: none">                    <source src="" type="video/mp4">                    <source src="" type="video/ogg">                    您的浏览器不支持Video标签。                </video>                <span style="display: none">X</span>                <input type="hidden" class="video-link-id" name="video_link_id" value="">            </li>            <li>//视频上传会比较久(上传完会有提示)</li>        </ul>    </div></div>

js代码:

$('.video-upload-file').on('change',function(){        layer.msg('正在提交视频......');        //隐藏按钮,显示进度条        $('.layui-upload-video').hide();        $('.layui-progress-ads').show();        var loads_video = layer.load(2,{shade: [0.2, '#3a3535']});      //产生加载圈,禁止用户其他操作        var thisFile = $(this);        var reader=new FileReader();        var file_size = this.files[0].size;     //文件大小        var limit = 8388608;        //每次读取文件的大小        // var limit = 1048000;        //每次读取文件的大小        var up_count = Math.ceil(file_size/limit);     //总上传次数        var type = this.files[0].type.substr(this.files[0].type.indexOf('/')+1);   //文件类型        var success_num = 0;        //用于存放上传成功的数据的id        var check = 1;             //防止多次合并        console.log('文件大小:'+this.files[0].size);        console.log('文件类型:'+type);        console.log('分割上传次数:'+up_count);        //分段读取文件        readFile(this.files[0], 0, limit);        function readFile(file, num, limit){            // console.log('第'+num+'次:'+num*limit);            reader.readAsDataURL(file.slice(num*limit, (num+1)*limit));            reader.onload = function(e){                console.log(reader.result.length);                console.log(reader.result);                //异步base64的数据传输到服务器                ajax_way(reader.result, name, num+1, thisFile);                if((num+1)*limit <= file_size){                    readFile(file, num+1, limit);                }            }        }        function ajax_way(data,name,num, thisFile){            //避免一次性生成太多的请求            if(num+1 > 60){                // console.log('等待两秒');                sleep(6000);                // console.log('等待结束');            }            $.ajax({                url: "<?= url('admin/video/up_mfile');?>",                type: "POST",                data: {video:data,name:name,num:num},                // async:false,      //是否采用同步,串行发送请求                success: function (data) {                    if(data.code == 1){                        //上传成功,成功次数加一                        success_num++;                        console.log(num+'完成');                        console.log('已完成:'+success_num+'/'+up_count);                        //计算完成的百分比                        var precentage = Math.ceil((success_num/up_count)*100);                        //更改进度条显示                        $('.layui-progress-ads-btn').attr('lay-percent', precentage+'%');                        $('.layui-progress-ads-btn').css('width', precentage+'%');                        $('.layui-progress-text').html(precentage+'%');                        //如果分割文件都上传了则调用接口合并文件                        if(success_num == up_count && check == 1){                            check = 0;                            success_num = 0;                            merge_mfile(name, up_count, thisFile, type);                        }                    }                },                error:function(e){                    console.log('出错了:'+num);                    //传输出错则重新上传                    ajax_way(data, name, num, thisFile);                }            });        }        //合并文件        function merge_mfile(name, count, thisFile, type){            $.ajax({                url:"<?= url('admin/video/merge_mfile');?>",                data:{name:name, count:count, type:type},                type:"POST",                success:function(data){                    if (data.code==1){                        layer.close(loads_video);                        layer.msg('视频提交成功');                        thisFile.siblings('.video-link-id').val(data.data);                    }else{                        layer.msg('视频提交异常请重新提交');                        //显示按钮,隐藏进度条                        $('.layui-upload-video').show();                        $('.layui-progress-ads').hide();                        //将进度条置零                        $('.layui-progress-ads-btn').attr('lay-percent', '0%');                        $('.layui-progress-ads-btn').css('width', '0%');                        $('.layui-progress-text').html('0%');                        //清空已选中的文件                        var file = $(".layui-upload-video-file-btn");                        file.after(file.clone().val(""));                        file.remove();                    }                }            })        }        function sleep(n) { //n表示的毫秒数            var start = new Date().getTime();            while (true) if (new Date().getTime() - start > n) break;        }        return false;    });

更多layui知识请关注layui使用教程栏目。

以上就是tp5+layui实现上传大文件介绍的详细内容,更多请关注其它相关文章!


  • 上一条:
    layui时间控件清空之后无法正常使用的问题
    下一条:
    React学习之JSX与react事件实例分析
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 使用 Alpine.js 排序插件对元素进行排序(0个评论)
    • 在js中使用jszip + file-saver实现批量下载OSS文件功能示例(0个评论)
    • 在vue中实现父页面按钮显示子组件中的el-dialog效果(0个评论)
    • 使用mock-server实现模拟接口对接流程步骤(0个评论)
    • vue项目打包程序实现把项目打包成一个exe可执行程序(0个评论)
    • 近期文章
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 在go + gin中gorm实现指定搜索/区间搜索分页列表功能接口实例(0个评论)
    • 在go语言中实现IP/CIDR的ip和netmask互转及IP段形式互转及ip是否存在IP/CIDR(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2017-06
    • 2017-07
    • 2017-08
    • 2017-09
    • 2017-10
    • 2017-11
    • 2018-03
    • 2018-04
    • 2018-05
    • 2018-06
    • 2018-09
    • 2018-11
    • 2018-12
    • 2019-02
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2021-04
    • 2021-05
    • 2021-07
    • 2021-08
    • 2021-09
    • 2021-10
    • 2021-11
    • 2022-08
    • 2022-09
    • 2022-10
    • 2022-11
    • 2022-12
    • 2023-01
    • 2023-02
    • 2023-03
    • 2023-04
    • 2023-05
    • 2023-06
    • 2023-07
    • 2023-09
    • 2023-10
    • 2023-11
    • 2023-12
    • 2024-01
    • 2024-02
    • 2024-03
    • 2024-04
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客