视频大文件分片上传(使用webuploader插件)

  • 公司做网盘系统,一直在调用图片服务器的接口上传图片,以前写的,以为简单改一改就可以用
  • 最初要求 php 上传多种视频格式,支持大文件,并可以封面截图,时长统计

问题

  • 1、上传到阿里云服务器,13秒左右,连接被重置
  • 2、切换到本地服务器后 413 Request Entity Too Large / nginx
  • 第2个问题还好,一般设置一下php.ini 和 nginx.conf 文件中的上传文件大小限制即可,但却不是最佳选项,因为一个视频2G算是正常大小,因此修改上传限制到2048MB不太现实,即使修改了也会超时。
  • 第1个问题,应该是阿里策略,不允许大文件上传,解决了第一个问题应该也会消失。

思考

  • 首先不考虑整个文件直接上传的方案,于是搜索,发现有分片上传这个名词,
  • 看了下原理,大概意思是将一个大文件按照一定尺寸进行切割,然后逐个发送到后台, 后台接收到所有的分片文件后,再组装成原文件。
  • 遂深入,发现出自百度的 webuploader ,支持分片、并发、预览压缩、拖拽、MD5秒传等
  • 看了几篇网上的使用案例以及官网的 getting-started.html, 总来来说网上的博客质量不高,有的浅尝辄止,有的代码缺失,有的只注重前端,有的将代码放到csdn,需要积分下载,
  • 官方的说明还可以,就是初始化的时候,案例中未标明变量的来源,作为一个后端,搞了好久才明白。
  • 故此写一篇文章以作备用。

本文将提供完整的代码和注释,js + php,因为前端本身是其他人的项目,我在这里只提供比较简单的代码, 既好理解也好套用。

<!DOCTYPE html>
<html>
<head>
<!--引入JQuery  插件基于JQuery-->
<script type="text/javascript" src="/resources/scripts/jquery-1.8.2.min.js"></script>

<!--引入插件的CSS文件-->
<link rel="stylesheet" type="text/css" href="/resources/webuploader/webuploader.css">

<!--引入插件的JS文件-->
<script type="text/javascript" src="/resources/webuploader/webuploader.js"></script>

<!--SWF在初始化的时候指定,在后面将展示-->


<title>视频</title>
</head>
<body class="video-body">
<div class="index-div">
    <!--从 uploader 开始,是上传相关代码-->
    <div id="uploader" class="wu-display">
        <!--用来存放文件信息-->
        <div id="thelist" class="uploader-list"></div>
        <div class="btns">
            <!--<input class="style_file_content" accept="video/mp4" type="file" id="upload_file_id"/>-->
            <div id="picker">选择文件</div>
            <button id="ctlBtn" class="btn btn-default" >开始上传</button>
            <button id="resetBtn" class="btn btn-default" >重试</button>
        </div>
    </div>
</div>
</body>
<script>

    $(function () {
        alert("uploader");
        $list = $(‘#thelist‘),
            $ctlBtn = $(‘#ctlBtn‘),
            $resetBtn = $(‘#resetBtn‘),
            state = ‘pending‘,
            uploader;
        // 初始化WebUploader插件
        uploader = WebUploader.create({

            // swf文件路径, 需要修改为你自己存放的路径
            swf: ‘/resources/webuploader/Uploader.swf‘,
            // 文件接收服务端。  // 需要修改为你的后端地址
            server: ‘http://self-pic.klagri.com.cn/api/file/video‘,
            // dnd 指定Drag And Drop拖拽的容器,如果不指定,则不启动
            // 禁用全局拖拽,否则在没有启动拖拽容器的情况下,视频拖进来后会直接在浏览器内播放。
            disableGlobalDnd: true,

            // 选择文件的按钮。可选。内部根据当前运行是创建,可能是input元素,也可能是flash.
            pick: {
                id: ‘#picker‘,                     // 对应 html 中的 picker
                innerHTML: ‘选择文件‘,   // 按钮上显示的文字
                multiple: true,                  // 多文件选择
            },

            // 允许视频和图片类型的文件上传。
            accept: {
                title: ‘Video‘,
                extensions: ‘mp4,gif,jpg,jpeg,bmp,png‘,      // 可以多个后缀,以逗号分隔, 不要有空格
                mimeTypes: ‘video/*,image/*‘
            },

            // 只允许选择图片文件。
            //accept: {
            // title: ‘Images‘,
            //  extensions: ‘‘,
            //  mimeTypes: ‘‘
            //}

            // thumb配置生成缩略图的选项, 此项交由后台完成, 所以前台未配置

            // 自动上传暂时关闭,使用多文件队列上传, 如果值为true,那么在选择完文件后,将直接开始上传文件,因为我还要做一些其他处理,故选择false。
            auto: false,

            //是否允许在文件传输时提前把下一个文件准备好。 对于一个文件的准备工作比较耗时,比如图片压缩,md5序列化。 如果能提前在当前文件传输期处理,可以节省总体耗时。
            prepareNextFile: true,

            // 可选,是否要分片处理大文件上传
            chunked: true,
            // 如果要分片,分多大一片?这里我设置为2M, 如需更大值,可能需要需修改php.ini等配置
            chunkSize:2*1024*1024,
            // 如果某个分片由于网络问题出错,允许自动重传多少次
            chunkRetry: 3,
            // 上传并发数,允许同时上传最大进程数,默认3
            threads:5,

            // formData {Object} [可选] [默认值:{}] 文件上传请求的参数表,每次发送都会发送此对象中的参数。 其实就是post中的表单数据,可自定义字段。
            formData: {
                context: 1,     // 这里是我的业务数据,你可以自定义或者去掉此项都可以
                from: "pan"    // 这里是我的业务数据,你可以自定义或者去掉此项都可以
            },
            //[可选] 验证文件总数量, 超出9个文件则不允许加入队列。
            fileNumLimit: 9,
            // 验证文件总大小是否超出限制(2G), 超出则不允许加入队列。根据需要进行设置。除了前面几个,其它都是可选项
            fileSizeLimit: 1024*1024*1024*2,
            // 验证单个文件大小是否超出限制(2G), 超出则不允许加入队列。
            fileSingleSizeLimit: 1024*1024*1024*2,
            // [可选] 去重, 根据文件名字、文件大小和最后修改时间来生成hash Key.
            duplicate: true,
            // 不压缩image, 默认如果是jpeg,文件上传前会压缩一把再上传!
            // resize: false,
            // 压缩选项
            compress: {
                // 如果压缩后比源文件大,则不压缩,图片有可能压缩后比原文件还大,需设置此项
                noCompressIfLarger: true,
            },
        });

        // 以下都是监听事件, 方法中的file 和 response 参数,需了解,并

        // 当有文件被添加进队列的时候触发,用于显示加载进度条
        uploader.on( ‘fileQueued‘, function( file ) {
            $list.append( ‘<div style="position: relative" id="‘ + file.id + ‘" class="item">‘ +
                ‘<h4 class="info" style="width: 150px; text-overflow: ellipsis">‘ + file.name + ‘</h4>‘ +
                ‘<p class="state" style="position: absolute; top: 0px; left: 120px; width: 120px; border: #00a2d4 solid 1px">正在加载...</p>‘ +
                ‘</div>‘ );
            var $li = $( ‘#‘+file.id );
            // 生成文件的MD5值, 可以用来实现秒传, 如不需要,可以忽略(数据库中保存md5值,如果存在相同md5,直接在文件服务器复制一份,不需再次分片上传以及合并,极快)
            uploader.md5File( file )
            // 及时显示进度
                .progress(function(percentage) {
                    $percent = $li.find(‘.state‘);
                    $li.find(‘p.state‘).text(‘加载中 ‘+  Math.round(percentage * 100)  + ‘%‘);
                    console.log(‘Percentage:‘, percentage);
                })
                // 完成
                .then(function(md5) {
                    // 将md5值加入到post的表单数据formData中, 与上文中的 context 和 from字段相同
                    uploader.option("formData",{
                        ... {"md5": md5}
                    });
                    console.log(‘md5:‘, md5);
                    alert("fileQueued")

                });
        });

        // 文件上传过程中创建进度条实时显示。
        // 显示进度条
        uploader.on( ‘uploadProgress‘, function( file, percentage ) {
            var $li = $( ‘#‘+file.id ),
                $percent = $li.find(‘.progress .progress-bar‘);

            // 避免重复创建
            if ( !$percent.length ) {
                
上一篇:java.util.Date转换到java.sql.date用于数据更新


下一篇:2/5 Vue.js 简单轮播组件