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, {
            width: 350,
            // 一個 panel 多個 tab
            tabs: [{
                // 標題
                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;
                    }
                }]
            }] // 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="\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中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 + '\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);
    }
}
復制代碼

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="width: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();

五、寫在最后

暫時想不到可以不修改源碼就實現視頻上傳的辦法


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM