.net core vue+wangEditor (双向绑定) 上传图片和视频功能

最终效果,是这样的,现在开始记录怎么做:

开始 npm 安装 wangEditor

安装好后,

因为要用vue 双向绑定 ,所以 我就把wangwangEditor 做成了一个封装组件,先看一下目录 :

我是把wangEditor写在了my-components这个项目下,新建一个 vue组件,代码如下:

<template>
    <div id="wangeditor">
        <div ref="editorElem" style="text-align:left"></div>
    </div>
</template>
<script>
    import E from 'wangeditor'
    export default {
        name: 'editorElem',
        data() {
            return {
                editor: null,
                editorContent: ''
            }
        },
        props: ['catchData', 'content'],    // 接收父组件的方法
        watch: {
            content() {
                this.editor.txt.html(this.content)
            }
        },
        mounted() {
            var imgUrl = "";
            this.editor = new E(this.$refs.editorElem)

            this.editor.customConfig.onchange = (html) => {
                this.editorContent = html
                this.catchData(this.editorContent)  // 把这个html通过catchData的方法传入父组件
            }
            this.editor.customConfig.uploadImgServer = '/api/Media/OnPostUpload'
            this.editor.customConfig.uploadVideoServer="/api/Media/OnPostUploadVideo" // 或 /node_modules/wangeditor/release/wangEditor.js 里直接写上传视频接口
            // 下面是最重要的的方法
            this.editor.customConfig.uploadImgHooks = {
                before: function (xhr, editor, files) {
                    // 图片上传之前触发
                    // xhr 是 XMLHttpRequst 对象,editor 是编辑器对象,files 是选择的图片文件

                    // 如果返回的结果是 {prevent: true, msg: 'xxxx'} 则表示用户放弃上传
                    // return {
                    //     prevent: true,
                    //     msg: '放弃上传'
                    // }
                },
                success: function (xhr, editor, result) {
                    // 图片上传并返回结果,图片插入成功之后触发
                    // xhr 是 XMLHttpRequst 对象,editor 是编辑器对象,result 是服务器端返回的结果
               
                    this.imgUrl = Object.values(result.data).toString()
                },
                fail: function (xhr, editor, result) {
                    debugger;
                    var res = xhr.data;
                    // 图片上传并返回结果,但图片插入错误时触发
                    // xhr 是 XMLHttpRequst 对象,editor 是编辑器对象,result 是服务器端返回的结果
                },
                error: function (xhr, editor) {
                    debugger;
                    // 图片上传出错时触发
                    // xhr 是 XMLHttpRequst 对象,editor 是编辑器对象
                },
                timeout: function (xhr, editor) {
                    // 图片上传超时时触发
                    // xhr 是 XMLHttpRequst 对象,editor 是编辑器对象
                },

                // 如果服务器端返回的不是 {errno:0, data: [...]} 这种格式,可使用该配置
                // (但是,服务器端返回的必须是一个 JSON 格式字符串!!!否则会报错)
                customInsert: function (insertImg, result, editor) {
                    // 图片上传并返回结果,自定义插入图片的事件(而不是编辑器自动插入图片!!!)
                    // insertImg 是插入图片的函数,editor 是编辑器对象,result 是服务器端返回的结果

                    // 举例:假如上传图片成功后,服务器端返回的是 {url:'....'} 这种格式,即可这样插入图片:
                    let url = Object.values(result.data)      // result.data就是服务器返回的图片名字和链接
                    JSON.stringify(url)    // 在这里转成JSON格式
                    insertImg(url)
                    // result 必须是一个 JSON 格式字符串!!!否则报错
                },
            };
            this.editor.customConfig.debug = true;
            this.editor.create()     // 创建富文本实例
            if (!this.content) {
                this.editor.txt.html('请编辑内容1')
            }
        }
    }
</script>

  然后,再在主页面上,引用 ,和感觉和后端差不多

<template>
<editorElem :catchData="catchData" :content="channelForm.content"></editorElem> (:content 这里就是双向绑定)
</template>

  import editorElem from "../../my-components/Editor.vue";

export default {

  name: "editor",
   components: {
       editorElem
   }

}

接着,开始改wangEidotr的视频上传代码,原wangEidotr上传视频用的不怎么好,所以我就去网上找了大神的( https://blog.csdn.net/m0_37885651/article/details/83660206 )代码修改了一下,

先找到wangEidotr.js 

//
/*
    menu - video
*/
// 构造函数
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._createInsertPanel();
    },
 
    _createInsertPanel: function _createInsertPanel() {
        var editor = this.editor;
        var uploadVideo = editor.uploadVideo;
        var config = editor.config;
 
        // id
        var upTriggerId = getRandom('up-trigger');
        var upFileId = getRandom('up-file');
 
        // tabs 的配置
        var tabsConfig = [{
            title: '上传 video',
            tpl: '<div class="w-e-up-img-container">\n                    ' +
            '<div id="' + upTriggerId + '" class="w-e-up-btn">\n                        ' +
            '<i class="w-e-icon-upload2"></i>\n                    </div>\n                    ' +
            '<div style="display:none;">\n                        <input id="' + upFileId + '" type="file" multiple="multiple" accept="audio/mp4, video/mp4"/>\n                    ' +
            '</div>\n                            </div>',
            events: [{
                // 触发选择视频
                selector: '#' + upTriggerId,
                type: 'click',
                fn: function fn() {
                    var $file = $('#' + upFileId);
                    var fileElem = $file[0];
                    if (fileElem) {
                        fileElem.click();
                    } else {
                        // 返回 true 可关闭 panel
                        return true;
                    }
                }
            }, {
                // 选择视频完毕
                selector: '#' + upFileId,
                type: 'change',
                fn: function fn() {
                    var $file = $('#' + upFileId);
                    var fileElem = $file[0];
                    if (!fileElem) {
                        // 返回 true 可关闭 panel
                        return true;
                    }
 
                    // 获取选中的 file 对象列表
                    var fileList = fileElem.files;
                    if (fileList.length) {
                        uploadVideo.uploadVideo(fileList);
                    }
 
                    // 返回 true 可关闭 panel
                    return true;
                }
            }]
        }
        ]; // tabs end
 
        // 判断 tabs 的显示
        var tabsConfigResult = [];
        tabsConfigResult.push(tabsConfig[0]);
 
        // 创建 panel 并显示
        var panel = new Panel(this, {
            width: 300,
            tabs: tabsConfigResult
        });
        panel.show();
 
        // 记录属性
        this.panel = panel;
    },
 
    // 试图改变 active 状态
    tryChangeActive: function tryChangeActive(e) {
        var editor = this.editor;
        var $elem = this.$elem;
        if (editor._selectedImg) {
            this._active = true;
            $elem.addClass('w-e-active');
        } else {
            this._active = false;
            $elem.removeClass('w-e-active');
        }
    }
};
 
 
/*
    所有菜单的汇总
*/
 
// 存储菜单的构造函数
var MenuConstructors = {};
 
MenuConstructors.video = Video;
// 构造函数
function UploadVideo(editor) {
    this.editor = editor;
}

// 原型
UploadVideo.prototype = {
    constructor: UploadVideo,
    // 根据 debug 弹出不同的信息
    _alert: function _alert(alertInfo, debugInfo) {
        var editor = this.editor;
        var debug = editor.config.debug;
        // var debug = true;
        var customAlert = editor.config.customAlert;

        if (debug) {
            throw new Error('wangEditor: ' + (debugInfo || alertInfo));
        } else {
            if (customAlert && typeof customAlert === 'function') {
                customAlert(alertInfo);
            } else {
                alert(alertInfo);
            }
        }
    },
    //插入视频的方法  需要单独定义
    insertLinkVideo:function(link){
        var _this3 = this;

        if (!link) {
            return;
        }
        var editor = this.editor;
        var config = editor.config;

        // 校验格式
        var linkVideoCheck = config.linkVideoCheck;
        var checkResult = void 0;
        if (linkVideoCheck && linkVideoCheck === 'function') {
            checkResult = linkVideoCheck(link);
            if (typeof checkResult === 'string') {
                // 校验失败,提示信息
                alert(checkResult);
                return;
            }
        }

        editor.cmd.do('insertHTML', '<video src="' + link + '" style="width:50%;height: 50%;" controls autobuffer autoplay muted/>');

        // 验证视频 url 是否有效,无效的话给出提示
        var video = document.createElement('video');
        video.onload = function () {
            var callback = config.linkVideoCallback;
            if (callback && typeof callback === 'function') {
                callback(link);
            }

            video = null;
        };
        video.onerror = function () {
            video = null;
            // 无法成功下载图片
            _this2._alert('插入视频错误', 'wangEditor: \u63D2\u5165\u56FE\u7247\u51FA\u9519\uFF0C\u56FE\u7247\u94FE\u63A5\u662F "' + link + '"\uFF0C\u4E0B\u8F7D\u8BE5\u94FE\u63A5\u5931\u8D25');
            return;
        };
        video.onabort = function () {
            video = null;
        };
        video.src = link;
    },
    // 上传视频
    uploadVideo: function uploadVideo(files) {
        var _this3 = this;

        if (!files || !files.length) {
            return;
        }

        // ------------------------------ 获取配置信息 ------------------------------
        var editor = this.editor;
        var config = editor.config;
        var uploadVideoServer = "/video/uploadVideo";//上传地址

        var maxSize = 100 * 1024 * 1024;       //100M
        var maxSizeM = maxSize / 1000 / 1000;
        var maxLength = 1;
        var uploadFileName = "file";
        var uploadVideoParams = config.uploadVideoParams || {};
        var uploadVideoHeaders = {};
        var hooks =config.uploadImgHooks || {};
        var timeout = 5 * 60 * 1000;        //5 min
        var withCredentials = config.withCredentials;
        if (withCredentials == null) {
            withCredentials = false;
        }

        // ------------------------------ 验证文件信息 ------------------------------
        var resultFiles = [];
        var errInfo = [];
        arrForEach(files, function (file) {
            var name = file.name;
            var size = file.size;

            // chrome 低版本 name === undefined
            if (!name || !size) {
                return;
            }

            if (/\.(mp4)$/i.test(name) === false) {
                // 后缀名不合法,不是视频
                errInfo.push('\u3010' + name + '\u3011\u4e0d\u662f\u89c6\u9891');
                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;
        }

        // ------------------------------ 自定义上传 ------------------------------
        // 添加视频数据
        var formdata = new FormData();
        arrForEach(resultFiles, function (file) {
            var name = uploadFileName || file.name;
            formdata.append(name, file);
        });

        // ------------------------------ 上传视频 ------------------------------
        if (uploadVideoServer && typeof uploadVideoServer === 'string') {
            // 添加参数
            var uploadVideoServer = uploadVideoServer.split('#');
            uploadVideoServer = uploadVideoServer[0];
            var uploadVideoServerHash = uploadVideoServer[1] || '';
            objForEach(uploadVideoParams, function (key, val) {
                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 {
                            console.log(result);
                            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.forEach(function (link) {
                            //     console.log(link);
                            //
                            // });
                            _this3.insertLinkVideo(data.url);
                        }

                        // 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);

            // 注意,要 return 。不去操作接下来的 base64 显示方式
            return;
        }
    }
};
// 修改原型
Editor.prototype = {
    constructor: Editor,
 
    // 添加视频上传
    _initUploadVideo: function _initUploadVideo() {
        this.uploadVideo = new UploadVideo(this);
    },
    // 创建编辑器
    create: function create() {
     
        // 添加 视频上传
        this._initUploadVideo();
    },
 
};

1,源码里找到Video 的构造函数 还有它的prototype,替换成第一部分。(有版本是一样的,可以不替换)
2,找到UploadImg的构造函数,还有它的prototype,这是上传图片的,相应的 你在这后面 加上第二部分UploadVideo的构造和原型,这是专门写的上传视频的。
3,在Editor原型上加个方法,_initUploadVideo , 然后在 创建编辑器 create 里面执行 this._initUploadVideo() ,加上就可以。

 

 

下面是后端代码:

 #region 上传图片 OnPostUpload
        [HttpPost]
        public async Task<IActionResult> OnPostUpload([FromServices]IHostingEnvironment environment)
        {
            List<string> fileUrl = new List<string>();
            var files = Request.Form.Files;
            if (string.IsNullOrWhiteSpace(environment.WebRootPath))
            {
                environment.WebRootPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot");
            }

            string webRootPath = environment.WebRootPath;
            string filePath = Path.Combine(webRootPath + "\\upload\\images");
            if (!Directory.Exists(filePath))
            {
                Directory.CreateDirectory(filePath);
            }

            foreach (var formFile in files)
            {
                if (formFile.Length > 0)
                {
                    var ext = Path.GetExtension(formFile.FileName);
                    if (!pictureFormatArray.Contains(ext.Split('.')[1]))
                    {
                        return new JsonResult(TmpUrl.ErrorInfo("图片格式不正确!", null));
                    }
                    var fileName = Guid.NewGuid().ToString() + ext;
                    var path = Path.Combine(webRootPath + "\\upload\\images", fileName);
                    using (var stream = new FileStream(path, FileMode.CreateNew))
                    {
                        await formFile.CopyToAsync(stream);
                        fileUrl.Add($"/api/Media/ShowNoticeImg?filePath={fileName}");
                    }
                }
            }

            return new JsonResult(TmpUrl.SuccessInfo("ok!", fileUrl));
        }
        #endregion

  #region 上传视频 OnPostUploadVideo
        [HttpPost]
        public async Task<IActionResult> OnPostUploadVideo([FromServices]IHostingEnvironment environment)
        {
            List<string> fileUrl = new List<string>();
            var files = Request.Form.Files;
            if (string.IsNullOrWhiteSpace(environment.WebRootPath))
            {
                environment.WebRootPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot");
            }

            string webRootPath = environment.WebRootPath;
            string filePath = Path.Combine(webRootPath + "\\upload\\videos");
            if (!Directory.Exists(filePath))
            {
                Directory.CreateDirectory(filePath);
            }

            foreach (var formFile in files)
            {
                if (formFile.Length > 0)
                {
                    var ext = Path.GetExtension(formFile.FileName);
                    if (!videoFormatArray.Contains(ext.Split('.')[1]))
                    {
                        return new JsonResult(TmpUrl.ErrorInfo("视频格式不正确!", null));
                    }
                    var fileName = Guid.NewGuid().ToString() + ext;
                    var path = Path.Combine(webRootPath + "\\upload\\videos", fileName);
                    using (var stream = new FileStream(path, FileMode.CreateNew))
                    {
                        await formFile.CopyToAsync(stream);
                        //fileUrl.Add($"/upload/videos/{fileName}");
                        fileUrl.Add("http://localhost:15429/upload/videos/8e11ae8e-8ecc-4b7c-afac-43601530493f.mp4");
                    }
                }
            }

            return new JsonResult(TmpUrl.SuccessInfo("ok!", fileUrl));
        }
        #endregion

        #region 获取图片流  ShowNoticeImg
        public IActionResult ShowNoticeImg(string filePath)
        {
            var contentTypeStr = "image/jpeg";
            string webRootPath = Path.Combine(Directory.GetCurrentDirectory(), $"wwwroot\\upload\\images\\{filePath}");
            using (var sw = new FileStream(webRootPath, FileMode.Open))
            {
                var bytes = new byte[sw.Length];
                sw.Read(bytes, 0, bytes.Length);
                sw.Close();
                return new FileContentResult(bytes, contentTypeStr);
            }
        }
        #endregion

 

转载于:https://www.cnblogs.com/wjwj/p/10871350.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值