zoukankan      html  css  js  c++  java
  • wangEditor上传本地视频

    一、实现效果

    实现效果

    img

    原本效果

    img

    二、源码

    下面是wangEditor实现插入视频的代码

    function Video(editor) {
        this.editor = editor;
        this.$elem = $('<div class="w-e-menu"><i class="w-e-icon-play"></i></div>');
        this.type = 'panel';
    
        // 当前是否 active 状态
        this._active = false;
    }
    
    // 原型
    Video.prototype = {
        constructor: Video,
        
        onClick: function onClick() {
            this._createPanel();
        },
        
        _createPanel: function _createPanel() {
            var _this = this;
    
            // 创建 id
            var textValId = getRandom('text-val');
            var btnId = getRandom('btn');
    
            // 创建 panel
            var panel = new Panel(this, {
                 350,
                // 一个 panel 多个 tab
                tabs: [{
                    // 标题
                    title: '插入视频',
                    // 模板
                    tpl: '<div><input id="' + textValId + '" type="text" class="block" placeholder="u683Cu5F0Fu5982uFF1A<iframe src=... ></iframe>"/><div class="w-e-button-container"><button id="' + btnId + '" class="right">u63D2u5165</button></div></div>',
                    // 事件绑定
                    events: [{
                        selector: '#' + btnId,
                        type: 'click',
                        fn: function fn() {
                            var $text = $('#' + textValId);
                            var val = $text.val().trim();
    
                            if (val) _this._insert(val); // 插入视频
    
                            // 返回 true,表示该事件执行完之后,panel 要关闭。否则 panel 不会关闭
                            return true;
                        }
                    }]
                }] // tabs end
            }); // panel end
    
            // 显示 panel
            panel.show();
    
            // 记录属性
            this.panel = panel;
        }
        
        // 插入视频
        _insert: function _insert(val) {
            var editor = this.editor;
            editor.cmd.do('insertHTML', val + '<p><br></p>');
        }
    };
    复制代码
    

    三、实现

    看完源码之后发现挺简单, 在创建panel的时候添加一个插入视频的panel,完事再实现一个视频上传、插入编辑器就完事了,参考一下文件上传代码。

    img

    1. 添加插入视频panel

    修改Video.prototype._createPanel方法

    _createPanel: function _createPanel() {
        var _this = this;
        var editor = this.editor;
        var uploadImg = editor.uploadImg;
        var config = editor.config;
    
        // 创建 id
        // 上传视频id
        var upTriggerVideoId = getRandom('up-trigger-video');
        var upFileVideoId = getRandom('up-file-video');
        // 插入视频id
        var textValId = getRandom('text-val');
        var btnId = getRandom('btn');
    
        // tabs 的配置
        var tabsConfig = [
            {
                title: '上传视频或pdf',
                tpl: '<div class="w-e-up-img-container"><div id="' + upTriggerVideoId + '" class="w-e-up-btn"><i class="w-e-icon-upload2"></i></div><div style="display:none;"><input id="' + upFileVideoId + '" type="file" multiple="multiple" accept="application/pdf,video/*"/></div></div>',
                events: [{
                    // 触发选择图片
                    selector: '#' + upTriggerVideoId,
                    type: 'click',
                    fn: function fn() {
                        var $file = $('#' + upFileVideoId);
                        var fileElem = $file[0];
                        if (fileElem) {
                            fileElem.click();
                        } else {
                            // 返回 true 可关闭 panel
                            return true;
                        }
                    }
                }, {
                    // 选择图片完毕
                    selector: '#' + upFileVideoId,
                    type: 'change',
                    fn: function fn() {
                        var $file = $('#' + upFileVideoId);
                        var fileElem = $file[0];
                        if (!fileElem) {
                            // 返回 true 可关闭 panel
                            return true;
                        }
    
                        // 获取选中的 file 对象列表
                        var fileList = fileElem.files;
                        if (fileList.length) {
                            console.log(fileList);
                            uploadImg.uploadVideo(fileList);
                        }
    
                        // 返回 true 可关闭 panel
                        return true;
                    }
                }]
            }, // first tab end
            {
                // 标题
                title: '插入视频',
                // 模板
                tpl: '<div><input id="' + textValId + '" type="text" class="block" placeholder="u683Cu5F0Fu5982uFF1A<iframe src=... ></iframe>"/><div class="w-e-button-container"><button id="' + btnId + '" class="right">u63D2u5165</button></div></div>',
                // 事件绑定
                events: [{
                    selector: '#' + btnId,
                    type: 'click',
                    fn: function fn() {
                        var $text = $('#' + textValId);
                        var val = $text.val().trim();
    
                        if (val) _this._insert(val); // 插入视频
    
                        // 返回 true,表示该事件执行完之后,panel 要关闭。否则 panel 不会关闭
                        return true;
                    }
                }]
            } // second tab end
        ]; // tabs end
    
        // 判断 tabs 的显示
        var tabsConfigResult = [];
        if (config.uploadVideoServer) {
            // 显示“上传视频”
            tabsConfigResult.push(tabsConfig[0]);
        }
        if (config.showLinkVideo) {
            // 显示“网络视频”
            tabsConfigResult.push(tabsConfig[1]);
        }
    
        // 创建 panel
        var panel = new Panel(this, {
             350,
            // 一个 panel 多个 tab
            tabs: tabsConfigResult // tabs end
        }); // panel end
    
        // 显示 panel
        panel.show();
    
        // 记录属性
        this.panel = panel;
    }
    复制代码
    

    2. 实现文件上传

    图片上传在UploadImg中uploadImg方法中实现,参考一下,在UploadImg中添加一个uploadVideo方法。

    // 上传视频
    UploadImg.prototype.uploadVideo: function uploadVideo(files) {
        var _this3 = this;
    
        if (!files || !files.length) {
            return;
        }
    
        // ------------------------------ 获取配置信息 ------------------------------
        var editor = this.editor;
        var config = editor.config;
        var uploadVideoServer = config.uploadVideoServer;
    
        var maxSize = config.uploadVideoMaxSize;
        var maxSizeM = maxSize / 1024 / 1024;
        var maxLength = config.uploadVideoMaxLength || 10000;
        var uploadFileName = config.uploadFileName || '';
        var uploadVideoParams = config.uploadVideoParams || {};
        var uploadVideoParamsWithUrl = config.uploadVideoParamsWithUrl;
        var uploadVideoHeaders = config.uploadVideoHeaders || {};
        var hooks = config.uploadVideoHooks || {};
        var timeout = config.uploadVideoTimeout || 30 * 60 * 1000; // 30分钟
        var withCredentials = config.withCredentials;
        if (withCredentials == null) {
            withCredentials = false;
        }
        var customUploadVideo = config.customUploadVideo;
    
        if (!customUploadVideo) {
            // 没有 customUploadVideo 的情况下,需要如下两个配置才能继续进行图片上传
            if (!uploadVideoServer) {
                return;
            }
        }
    
        // ------------------------------ 验证文件信息 ------------------------------
        var resultFiles = [];
        var errInfo = [];
        arrForEach(files, function (file) {
            var name = file.name;
            var size = file.size;
    
            // chrome 低版本 name === undefined
            if (!name || !size) {
                return;
            }
    
            if (/.(pdf|rm|rmvb|3gp|avi|mpeg|mpg|mkv|dat|asf|wmv|flv|mov|mp4|ogg|ogm)$/i.test(name) === false) {
                // 后缀名不合法,不是视频
                errInfo.push('u3010' + name + 'u3011u4E0Du662Fu56FEu7247');
                return;
            }
            if (maxSize < size) {
                // 上传视频过大
                errInfo.push('u3010' + name + 'u3011u5927u4E8E ' + maxSizeM + 'M');
                return;
            }
    
            // 验证通过的加入结果列表
            resultFiles.push(file);
        });
        // 抛出验证信息
        if (errInfo.length) {
            this._alert('视频验证未通过: 
    ' + errInfo.join('
    '));
            return;
        }
        if (resultFiles.length > maxLength) {
            this._alert('一次最多上传' + maxLength + '个视频');
            return;
        }
    
        // ------------------------------ 自定义上传 ------------------------------
        if (customUploadVideo && typeof customUploadVideo === 'function') {
            customUploadVideo(resultFiles, this.insertLinkVideo.bind(this));
    
            // 阻止以下代码执行
            return;
        }
    
        // 添加图片数据
        var formdata = new FormData();
        arrForEach(resultFiles, function (file) {
            var name = uploadFileName || file.name;
            formdata.append(name, file);
        });
    
        // ------------------------------ 上传图片 ------------------------------
        if (uploadVideoServer && typeof uploadVideoServer === 'string') {
            // 添加参数
            var uploadVideoServerArr = uploadVideoServer.split('#');
            uploadVideoServer = uploadVideoServerArr[0];
            var uploadVideoServerHash = uploadVideoServerArr[1] || '';
            objForEach(uploadVideoParams, function (key, val) {
                // 因使用者反应,自定义参数不能默认 encode ,由 v3.1.1 版本开始注释掉
                // val = encodeURIComponent(val)
    
                // 第一,将参数拼接到 url 中
                if (uploadVideoParamsWithUrl) {
                    if (uploadVideoServer.indexOf('?') > 0) {
                        uploadVideoServer += '&';
                    } else {
                        uploadVideoServer += '?';
                    }
                    uploadVideoServer = uploadVideoServer + key + '=' + val;
                }
    
                // 第二,将参数添加到 formdata 中
                formdata.append(key, val);
            });
            if (uploadVideoServerHash) {
                uploadVideoServer += '#' + uploadVideoServerHash;
            }
    
            // 定义 xhr
            var xhr = new XMLHttpRequest();
            xhr.open('POST', uploadVideoServer);
    
            // 设置超时
            xhr.timeout = timeout;
            xhr.ontimeout = function () {
                // hook - timeout
                if (hooks.timeout && typeof hooks.timeout === 'function') {
                    hooks.timeout(xhr, editor);
                }
    
                _this3._alert('上传视频超时');
            };
    
            // 监控 progress
            if (xhr.upload) {
                xhr.upload.onprogress = function (e) {
                    var percent = void 0;
                    // 进度条
                    var progressBar = new Progress(editor);
                    if (e.lengthComputable) {
                        percent = e.loaded / e.total;
                        progressBar.show(percent);
                    }
                };
            }
    
            // 返回数据
            xhr.onreadystatechange = function () {
                var result = void 0;
                if (xhr.readyState === 4) {
                    if (xhr.status < 200 || xhr.status >= 300) {
                        // hook - error
                        if (hooks.error && typeof hooks.error === 'function') {
                            hooks.error(xhr, editor);
                        }
    
                        // xhr 返回状态错误
                        _this3._alert('上传视频发生错误', 'u4E0Au4F20u56FEu7247u53D1u751Fu9519u8BEFuFF0Cu670Du52A1u5668u8FD4u56DEu72B6u6001u662F ' + xhr.status);
                        return;
                    }
    
                    result = xhr.responseText;
                    if ((typeof result === 'undefined' ? 'undefined' : _typeof(result)) !== 'object') {
                        try {
                            result = JSON.parse(result);
                        } catch (ex) {
                            // hook - fail
                            if (hooks.fail && typeof hooks.fail === 'function') {
                                hooks.fail(xhr, editor, result);
                            }
    
                            _this3._alert('上传视频失败', '上传视频返回结果错误,返回结果是: ' + result);
                            return;
                        }
                    }
                    if (!hooks.customInsert && result.errno != '0') {
                        // hook - fail
                        if (hooks.fail && typeof hooks.fail === 'function') {
                            hooks.fail(xhr, editor, result);
                        }
    
                        // 数据错误
                        _this3._alert('上传视频失败', '上传视频返回结果错误,返回结果 errno=' + result.errno);
                    } else {
                        if (hooks.customInsert && typeof hooks.customInsert === 'function') {
                            // 使用者自定义插入方法
                            hooks.customInsert(_this3.insertLinkVideo.bind(_this3), result, editor);
                        } else {
                            // 将图片插入编辑器
                            var data = result.data || [];
                            data.forEach(function (link) {
                                _this3.insertLinkVideo(link);
                            });
                        }
    
                        // hook - success
                        if (hooks.success && typeof hooks.success === 'function') {
                            hooks.success(xhr, editor, result);
                        }
                    }
                }
            };
    
            // hook - before
            if (hooks.before && typeof hooks.before === 'function') {
                var beforeResult = hooks.before(xhr, editor, resultFiles);
                if (beforeResult && (typeof beforeResult === 'undefined' ? 'undefined' : _typeof(beforeResult)) === 'object') {
                    if (beforeResult.prevent) {
                        // 如果返回的结果是 {prevent: true, msg: 'xxxx'} 则表示用户放弃上传
                        this._alert(beforeResult.msg);
                        return;
                    }
                }
            }
    
            // 自定义 headers
            objForEach(uploadVideoHeaders, function (key, val) {
                xhr.setRequestHeader(key, val);
            });
    
            // 跨域传 cookie
            xhr.withCredentials = withCredentials;
    
            // 发送请求
            xhr.send(formdata);
        }
    }
    复制代码
    

    3. 插入编辑器

    插入视频也写在UploadImg.prototype中

    // 根据链接插入视频
    insertLinkVideo: function insertLinkVideo(link) {
        if (!link) return;
        
        var _this2 = this;
    
        var editor = this.editor;
        var config = editor.config;
    
        // 校验格式
        var linkVideoCheck = config.linkVideoCheck;
        var checkResult = void 0;
        if (linkVideoCheck && typeof linkVideoCheck === 'function') {
            checkResult = linkVideoCheck(link);
            if (typeof checkResult === 'string') {
                // 校验失败,提示信息
                alert(checkResult);
                return;
            }
        }
    
        editor.cmd.do('insertHTML', '<iframe src="' + link + '" style="650px;height: 366px" frameborder="0"></iframe>');
    }
    

    4. 添加视频上传的默认参数

    在config中添加一些上传视频默认参数, 加不加无所谓

    // 是否显示添加网络视频的 tab
    showLinkVideo: true,
    
    // 插入网络视频的回调
    linkVideoCallback: function linkVideoCallback(url) {
        // console.log(url)  // url 即插入视频的地址
    },
    
    // 默认上传视频 max size: 512M
    uploadVideoMaxSize: 512 * 1024 * 1024,
    
    // 配置一次最多上传几个视频
    uploadVideoMaxLength: 5,
    
    // 上传视频的自定义参数
    uploadVideoParams: {
        // token: 'abcdef12345'
    },
    
    // 上传视频的自定义header
    uploadVideoHeaders: {
        // 'Accept': 'text/x-json'
    },
    
    // 自定义上传视频超时时间 30分钟
    uploadVideoTimeout: 30 * 60 * 1000,
    
    // 上传视频 hook 
    uploadVideoHooks: {
        // customInsert: function (insertLinkVideo, result, editor) {
        //     console.log('customInsert')
        //     // 视频上传并返回结果,自定义插入视频的事件,而不是编辑器自动插入视频
        //     const data = result.data1 || []
        //     data.forEach(link => {
        //         insertLinkVideo(link)
        //     })
        // },
        before: function before(xhr, editor, files) {
            // 视频上传之前触发
    
            // 如果返回的结果是 {prevent: true, msg: 'xxxx'} 则表示用户放弃上传
            // return {
            //     prevent: true,
            //     msg: '放弃上传'
            // }
        },
        success: function success(xhr, editor, result) {
            // 视频上传并返回结果,视频插入成功之后触发
        },
        fail: function fail(xhr, editor, result) {
            // 视频上传并返回结果,但视频插入错误时触发
        },
        error: function error(xhr, editor) {
            // 视频上传出错时触发
        },
        timeout: function timeout(xhr, editor) {
            // 视频上传超时时触发
        }
    }
    

    四、使用

    初始化编辑器,配置上传视频参数

    var editor = new window.wangEditor('#text-editor');
    // 图片上传
    editor.customConfig.uploadImgServer = 'upload/editUpload'; // 上传接口
    editor.customConfig.uploadFileName = 'files'; // 上传文件参数名
    editor.customConfig.uploadImgHooks = { // 上传完成处理方法
        customInsert: function (insertImg, result) {
            if (result.ret === 200) {
                (result.data || '').split(',').forEach(function (link) {
                    link && insertImg(link);
                });
            } else {
                flavrShowByTime('上传失败', null, 'danger');
            }
        }
    };
    // 视频上传
    editor.customConfig.uploadVideoServer = 'editUpload'; // 上传接口
    editor.customConfig.uploadVideoHooks = { // 上传完成处理方法
        customInsert: function (insertVideo, result) {
            if (result.ret === 200) {
                (result.data || '').split(',').forEach(function (link) {
                    link && insertVideo(link);
                });
            } else {
                flavrShowByTime('上传失败', null, 'danger');
            }
        }
    };
    editor.create();
    

    五、写在最后

    暂时想不到可以不修改源码就实现视频上传的办法

  • 相关阅读:
    idea从maven导入jar包
    java zip4j压缩打包zip
    three.js一步一步来--如何画出一个逃跑的圆柱体
    three.js一步一步来--如何用线画出一个面--网格板子
    three.js一步一步来--如何画出一个转动的正方体
    three.js一步一步来--如何画出一根线
    假如你想在VUE的main.js里根据条件按需引入注册组件以及样式,那就这样子写,附赠自己写的vue一个框架配置多系统按需加载系统路由以及组件办法
    React Hook 的底层实现原理
    测试Markdown
    Linux学习总结(十六)系统用户及用户组管理
  • 原文地址:https://www.cnblogs.com/ajaemp/p/13055642.html
Copyright © 2011-2022 走看看