在vue中使用wangEditor上传视频

一、效果展示

实现效果
在vue中使用wangEditor上传视频_第1张图片

原本效果
在vue中使用wangEditor上传视频_第2张图片

二、修改wangEditor源码

  1. 添加插入视频panel

只修改Video.prototype._createPanel方法

// 原型
Video.prototype = {
	_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: '
+ upTriggerVideoId + '" class="w-e-up-btn">
+ upFileVideoId + '" type="file" multiple="multiple" accept="application/pdf,video/*"/>
'
, 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: '
+ textValId + '" type="text" class="block" placeholder="\u683C\u5F0F\u5982\uFF1A"/>
'
, // 事件绑定 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; }, // 插入视频 _insert: function _insert(val) { var editor = this.editor; editor.cmd.do('insertHTML', val + '


'
); } }
  1. 实现文件上传
    添加代码的位置如下 ↓↓↓
    在vue中使用wangEditor上传视频_第3张图片

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

// 上传视频
//UploadImg.prototype.uploadVideo: function uploadVideo(files) {} // 写在外面的写法
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);
    }
}
  1. 插入编辑器

插入视频也写在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', '');
}
  1. 添加视频上传的默认参数

config中添加一些上传视频默认参数

添加代码的位置如下 ↓↓↓
在vue中使用wangEditor上传视频_第4张图片

// 是否显示添加网络视频的 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();

vue中使用七牛云上传视频代码 ↓↓↓ 博主github源码地址

<template>
	<div ref="editor"></div>
</template>

<script>
import E from 'zhangeditor'  //引入插件

data() {
    return {
      editor: null
    }
 },
 methods: {
	this.editor = new E(this.$refs.editor)
	//上传到七牛云存储  后端接口
	zhangApi.qiniuToken({ showPub: true }).then(res => {
      this.uploadToken = res.data.token
      this.editor.customConfig.uploadToken = res.data.token
      this.editor.customConfig.uploadVideoServer = 'http://up-z2.qiniup.com/'
      // 上传接口
      this.editor.customConfig.uploadVideoHooks = {
        // 上传完成处理方法
        customInsert: function(insertVideo, result) {
          //后端接口
          zhangApi.qiniuUrl({ key: result.key, showPub: false }).then(res => {
            insertVideo(res.data.url)
          })
        }
      }
      this.editor.create() // 创建富文本实例
    })
}
</script>

修改uploadVideo部分源码

//上传视频--------------------------------------------------------------------
uploadVideo: function uploadVideo(files) {
	// ------------------------------ 获取配置信息 ---------------------------
	var uploadToken = config.uploadToken; //新增uploadToken
	
	var xhr = new XMLHttpRequest();
	xhr.open('POST', uploadVideoServer);
	
	formdata.append('token', uploadToken);
	// 发送请求
	xhr.send(formdata);
	}

上传网络视频地址教程传送带

总结

  • 问题1:标签插入的是iframe但无法全屏播放

iframe标签加上webkitallowfullscreen="" mozallowfullscreen="" allowfullscreen="" 属性
allowfullscreen:用于设置iframe中的信息是否允许开启全屏状态

<iframe webkitallowfullscreen="" mozallowfullscreen="" allowfullscreen="" id="video-iframe" frameborder="0" src=""></iframe>
  • 问题2:标签插入的是iframe但无法全屏播放后换成video
    换成video标签后在编辑器就不能在视频前编辑内容

  • 问题3:开启七牛云配置无法再使用插入网络图片
    wangEditor3使用手册这里有写配置七牛云后无法使用插入网络图片,这里没有使用它自带的七牛云配置,但是自己写的上传网络视频的是可以的

  • 问题4:iframe加上全屏后,在PC端没问题,数据传到移动端全屏后把安卓本身的屏幕换了方向
    全屏显示视频没问题,但是过程体验不好,只好先取消了全屏状态,目前不知道如何处理。。。

  • 问题5:在没改源码前我用的是ant-design的上传组件,绝对定位了个按钮,但是它的问题是必须要点击一下富文本,得到富文本的焦点才能上传成功
    效果图 ↓↓↓
    在vue中使用wangEditor上传视频_第5张图片

<a-upload
	:action="uploadAction"
	:data="{ token: uploadToken && uploadToken.token }"
	:beforeUpload="beforeVideoUpload"
	@change="videoUploadChange"
	:showUploadList="false"
	accept="video/*"
	>
	<a-icon type="youtube" theme="outlined" class="upload-btn" />
</a-upload>


 // 上传视频
beforeVideoUpload(file) {
	return new Promise((resolve, reject) => {
	// 上传 step 1/3 拿到七牛token数据
		zhangApi.qiniuToken({ showPub: true }).then(res => {
			this.uploadToken = res.data
			resolve(file)
		})
	})
},
videoUploadChange(info) {
	if (info.file.status === 'uploading') {
		this.uploadLoading = true
		return
	}
	if (info.file.status === 'done') {
		var response = info.file.response
		this.uploadLoading = false
		// 上传 step 3/3 拿到url
		zhangApi.qiniuUrl({ key: response.key, showPub: false }).then(res => {
			let iframe = res.data.url
			this.editor.txt.append(
			""
			) //把视频链接赋值给editor
			if (iframe) {
				// this.$Message.success('上传视频成功!')
			} else {
				this.$Message.error('上传视频失败!')
			}
		})
	}
}
.upload-btn {
  position: absolute;
  cursor: pointer;
  top: 14px;
  right: 60px;
}
  • 问题6:修改源码后到不同环境打包依赖包应该是不会有变化的
    我把它单独提出来做的修改,然后相当于自己的插件,去上传到npm上使用的,上传npm教程我也有写, 地址在这,然后在自己项目中npm install zhangeditor去安装自己的插件使用,有了解的大佬欢迎指导该如何正确修改源码后使用O(∩_∩)O~

参考来源:https://www.lagou.com/lgeduarticle/99623.html

你可能感兴趣的:(npm,vue,vue.js,wangEditor编辑器,npm)