wangEditor编辑器添加上传视频功能

avatar 2020年5月2日13:36:07 评论 29 views

正在帮一个朋友的项目进行一些修改,该项目中使用的是 wangEditor 富文本编辑器。

该编辑器的上传视频有个缺陷,不能手动上传,这是目前的效果图

朋友要求加一个上传视频的功能。

网上的解决方案的文章很多,这里亲自尝试了一下,成功解决。

参考文章如下:https://www.lagou.com/lgeduarticle/99623.html

 

下面我说一下主要修改的几个地方

具体流程如下

找到 wangEditor.js

注意:引用js的地方要改成 wangEditor.js,不要写成 wangEditor.min.js

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: '上传视频',
            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="\u683C\u5F0F\u5982\uFF1A<iframe src=... ></iframe>"/><div class="w-e-button-container"><button id="' + btnId + '" class="right">\u63D2\u5165</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, {
        width: 350,
        // 一个 panel 多个 tab
        tabs: tabsConfigResult // tabs end
    }); // panel end

    // 显示 panel
    panel.show();

    // 记录属性
    this.panel = panel;
},

 

 

2. 实现文件上传和插入编辑器

在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 + '\u3011\u4E0D\u662F\u56FE\u7247');
            return;
        }
        if (maxSize < size) {
            // 上传视频过大
            errInfo.push('\u3010' + name + '\u3011\u5927\u4E8E ' + maxSizeM + 'M');
            return;
        }

        // 验证通过的加入结果列表
        resultFiles.push(file);
    });
    // 抛出验证信息
    if (errInfo.length) {
        this._alert('视频验证未通过: \n' + errInfo.join('\n'));
        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('上传视频发生错误', '\u4E0A\u4F20\u56FE\u7247\u53D1\u751F\u9519\u8BEF\uFF0C\u670D\u52A1\u5668\u8FD4\u56DE\u72B6\u6001\u662F ' + 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);
    }
},

// 根据链接插入视频
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="width:650px;height: 366px" frameborder="0"></iframe>');
}

 

 

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

在config中添加一些上传视频默认参数, 加不加无所谓,在使用方法中都做了参数判断,为了规范代码,这里添加一下。

找到 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) {
            // 视频上传超时时触发
        }
    }

 

 

二、具体使用

1、引入 css

<link rel="stylesheet" href="/resources/wangEditor/wangEditor.min.css">

 

2、引入 js

<script src="/resources/wangEditor/wangEditor.js"></script>

 

3、编辑器div

<div id="editor"></div>

 

4、JavaScript 代码

<script type="text/javascript">

    $(function () {
        var E = window.wangEditor;
        var editor = new E('#editor');
        editor.customConfig.uploadFileName = 'file';
        editor.customConfig.uploadImgServer = '/common/upload';
        // 将图片大小限制为 5MB
        editor.customConfig.uploadImgMaxSize = 1024 * 1024 * 1024;
        // 限制一次最多上传 5 张图片
        editor.customConfig.uploadImgMaxLength = 10;
        // 将 timeout 时间改为 10s
        editor.customConfig.uploadImgTimeout = 10000;
        editor.customConfig.menus = [
            'head',  // 标题
            'bold',  // 粗体
            'fontSize',  // 字号
            'fontName',  // 字体
            'italic',  // 斜体
            'underline',  // 下划线
            'strikeThrough',  // 删除线
            'foreColor',  // 文字颜色
            'backColor',  // 背景颜色
            'link',  // 插入链接
            'list',  // 列表
            'justify',  // 对齐方式
            'quote',  // 引用
            'emoticon',  // 表情
            'image',  // 插入图片
            'table',  // 表格
            'video',  // 插入视频
            'code',  // 插入代码
            'undo',  // 撤销
            'redo'  // 重复
        ];
        editor.customConfig.emotions = [
            {
                title: '默认',
                type: 'image',
                content: defaultEmotions
            },
            {
                title: '动漫',
                type: 'image',
                content: animeEmotions
            },
            {
                title: 'GIF',
                type: 'image',
                content: gifEmotions
            },
            {
                title: '其他',
                type: 'image',
                content: otherEmotions
            }
        ];

        // 视频上传
        editor.customConfig.uploadVideoServer = '/common/upload'; // 上传接口
        editor.customConfig.uploadVideoHooks = { // 上传完成处理方法
            customInsert: function (insertVideo, result) {
                console.log(result);
                if (result.errno === 0) {
                    $.each(result.data,function(index,value){
                        insertVideo(value);
                    });
                } else {
                    alert('上传失败');
                }
            }
        };

        editor.create();
        
    })



</script>

 

5、后台代码

/**
 * 文件上传接口
 * @param file: 要上传的文件对象
 * @param customPath: 自定义存放路径,格式 xxx/xxx/xxx,最后一个目录没有 "/"
 * @return 返回的是JSON,{errno: 状态,data: 文件访问URLs数组}
 */
@ResponseBody
@RequestMapping(value = "/upload", method = RequestMethod.POST)
private Map<String, Object> upload(@RequestParam("file") MultipartFile file, @RequestParam(value = "customPath",defaultValue = "topic") String customPath) {
   JSONObject jsonObject = new JSONObject();
   String[] data = {storageService.store(file, Paths.get(customPath))};
   jsonObject.put("errno", 0);
   jsonObject.put("data", data);
   return jsonObject;
}

data是文件URL数组

 

三、效果图

wangEditor编辑器添加上传视频功能

四、wangEditor下载

官网下载:http://www.wangeditor.com/index.html

博主已经修改了 wangEditor.js ,打包一下,方便大家下载

wangEditor

  • 微信
  • 交流学习,有偿服务
  • weinxin
  • 博客/Java交流群
  • 资源分享,问题解决,技术交流。群号:590480292
  • weinxin
avatar

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: