.net5项目集成百度富文本编辑器umeditor最全教程(含源码)

news2024/11/19 22:40:03

目前百度的umeditor已经停止维护了,net版本的分支源码包也停留在了net farmework4左右的版本,对于想要集成这款富文本编辑器到net5平台,具有较大难度,主要体现在以下几个方面:

  1. umeditor源码需要改造,需要具有熟练掌握js技术、调试技术

  1. net5相对于net framework部分类库更新或者移除了,需要能够看懂提供的源码的具体意义后进行修改。需要掌握c#编程。

下面,我来说说怎么去集成。

一、下载umeditor源码

我提供了百度网盘链接:http://t.zoukankan.com/feigao-p-4608844.html,从这个链接拉倒最下面,感谢这位作者的无私奉献。方便大家下载。

二、新建一个html页面,方便调用ajax访问后端接口的那种,有开发经验的朋友都懂,搞一套基础环境出来!然后在html页面应用下面截图中的文件,我同时集成了layui框架,不过不影响!

然后打开页面,就会出现你想要的富文本编辑器,如下:

当你内心很兴奋的时候,可以说一声,好简单啊。。。😄

但是当你打开f12浏览器调试模式的时候,你就会一脸懵逼,因为提示你:“后台配置项返回格式出错,上传功能将不能正常使用!”,此时你除了可以在富文本上输入文本之外,其他都没用😭,具体如下图:

这将是你面对的第一个棘手的问题:“后台配置项返回格式出错,上传功能将不能正常使用!

下面我来说明下原因:原来想要使用umeditor,你得首先在web api写个接口,让编辑器的前端能够获取到一大批配置文件。下面,我来写下步骤和源码。

2.1、把源码中的config.json复制一份,放到后端项目,和appsettings.json在同级目录,如下图:

2.2 写个接口,让之前新建的h5页面可以通过ajax调用到。我写成了一个通用接口,不要标记[HttpPost]或者[HttpGet]特性,这样get请求和post请求都可以使用。代码如下:

        public void TestApi()
        {
            var queryParam = HttpContext.Request.QueryString;
            string queryData = queryParam.Value.Remove(0,1);
            var targetWord = queryData.Split("&")[0].Split("=")[1];
            Handler action = null;
            switch (targetWord)
            {
                case "config":
                    action = new ConfigHandler(HttpContext);
                    action.Process();
                    break;
                //case "uploadimage":
                    //action = new UploadHandler(HttpContext, new UploadConfig()
                    //{
                       // AllowExtensions = Config.GetStringList("imageAllowFiles"),
                        //PathFormat = Config.GetString("imagePathFormat"),
                       // SizeLimit = Config.GetInt("imageMaxSize"),
                       // UploadFieldName = Config.GetString("imageFieldName")
                   // });
                   // action.Process();
                    //break;
                    #region  下面的是其他类型的每天文件,按需添加
                    //case "uploadscrawl":
                    //    action = new UploadHandler(context, new UploadConfig()
                    //    {
                    //        AllowExtensions = new string[] { ".png" },
                    //        PathFormat = Config.GetString("scrawlPathFormat"),
                    //        SizeLimit = Config.GetInt("scrawlMaxSize"),
                    //        UploadFieldName = Config.GetString("scrawlFieldName"),
                    //        Base64 = true,
                    //        Base64Filename = "scrawl.png"
                    //    });
                    //    break;
                    //case "uploadvideo":
                    //    action = new UploadHandler(context, new UploadConfig()
                    //    {
                    //        AllowExtensions = Config.GetStringList("videoAllowFiles"),
                    //        PathFormat = Config.GetString("videoPathFormat"),
                    //        SizeLimit = Config.GetInt("videoMaxSize"),
                    //        UploadFieldName = Config.GetString("videoFieldName")
                    //    });
                    //    break;
                    //case "uploadfile":
                    //    action = new UploadHandler(context, new UploadConfig()
                    //    {
                    //        AllowExtensions = Config.GetStringList("fileAllowFiles"),
                    //        PathFormat = Config.GetString("filePathFormat"),
                    //        SizeLimit = Config.GetInt("fileMaxSize"),
                    //        UploadFieldName = Config.GetString("fileFieldName")
                    //    });
                    //    break;
                    //case "listimage":
                    //    action = new ListFileManager(context, Config.GetString("imageManagerListPath"), Config.GetStringList("imageManagerAllowFiles"));
                    //    break;
                    //case "listfile":
                    //    action = new ListFileManager(context, Config.GetString("fileManagerListPath"), Config.GetStringList("fileManagerAllowFiles"));
                    //    break;
                    //case "catchimage":
                    //    action = new CrawlerHandler(context);
                    //    break;
                    //default:
                    //    action = new NotSupportedHandler(context);
                    //    break;
                    #endregion
            }
            
        }

    /// <summary>
    /// Config 的摘要说明
    /// </summary>
    public static class Config
    {
        private static bool noCache = true;
        private static JObject BuildItems()
        {
            var json = File.ReadAllText(Environment.CurrentDirectory + "/" + "config.json");
            return JObject.Parse(json);
        }

        public static JObject Items
        {
            get
            {
                if (noCache || _Items == null)
                {
                    _Items = BuildItems();
                }
                return _Items;
            }
        }
        private static JObject _Items;


        public static T GetValue<T>(string key)
        {
            return Items[key].Value<T>();
        }

        public static string[] GetStringList(string key)
        {
            return Items[key].Select(x => x.Value<string>()).ToArray();
        }

        public static string GetString(string key)
        {
            return GetValue<string>(key);
        }

        public static int GetInt(string key)
        {
            return GetValue<int>(key);
        }
    }

    #region 配置项请求处理模块
    /// <summary>
    /// Config 的摘要说明
    /// </summary>
    public class ConfigHandler : Handler
    {
        public ConfigHandler(HttpContext context) : base(context) { }

        public override void Process()
        {
            WriteJson(Config.Items);
        }
    }


    /// <summary>
    /// Handler 的摘要说明
    /// </summary>
    public abstract class Handler
    {
        public Handler(HttpContext context)
        {
            this.Request = context.Request;
            this.Response = context.Response;
            this.Context = context;
            //this.Server = context.Server;
        }

        public abstract void Process();

        protected void WriteJson(object response)
        {
            var queryParam = Request.QueryString;
            string queryData = queryParam.Value.Remove(0, 1);
            var targetList = queryData.Split("&").ToList(); 
            string jsonpCallback = "";
            foreach (var target in targetList)
            {
                if (target.Split("=")[0] == "callback")
                {
                    jsonpCallback = target.Split("=")[1];
                }
            }
            string json = JsonConvert.SerializeObject(response);
            if (string.IsNullOrWhiteSpace(jsonpCallback))
            {
                Response.Headers.Add("Content-Type", "text/plain");
                Response.WriteAsync(json);
            }
            else
            {
                Response.Headers.Add("Content-Type", "application/javascript");
                Response.WriteAsync(string.Format("{0}({1});", jsonpCallback, json));
            }
        }

        public HttpRequest Request { get; private set; }
        public HttpResponse Response { get; private set; }
        public HttpContext Context { get; private set; }
        //public HttpServerUtility Server { get; private set; }
    }
    #endregion

然后需要在ueditor.config.js修改下请求地址 ,这个每个人可以自己配置。

等这一步做完,你会发现上面的问题就解决了。但是又会出现一个新的问题,也就是上传图片、视频等文件失败。如下:

2.3下面说一下这个问题的解决方案:

首先,将上面控制器中的部分代码取消注释:

2.4、然后修改下,修改图片的保存路径和http链接路径。

2.5、图片文件上传后端代码如下:你需要在保存路径那边自己做点修改。

    #region 上传图片配置
    /// <summary>
    /// UploadHandler 的摘要说明
    /// </summary>
    public class UploadHandler : Handler
    {

        public UploadConfig UploadConfig { get; private set; }
        public UploadResult Result { get; private set; }

        public UploadHandler(HttpContext context, UploadConfig config)
            : base(context)
        {
            this.UploadConfig = config;
            this.Result = new UploadResult() { State = UploadState.Unknown };
        }

        public override void Process()
        {
            byte[] uploadFileBytes = null;
            string uploadFileName = null;
           
            if (UploadConfig.Base64)
            {
                uploadFileName = UploadConfig.Base64Filename;
                uploadFileBytes = Convert.FromBase64String(Request.Form[UploadConfig.UploadFieldName]);
                Result.OriginFileName = uploadFileName;
                var savePath = PathFormatter.Format(uploadFileName, UploadConfig.PathFormat);
                var localPath = Environment.CurrentDirectory + "/wwwroot" + savePath;
                try
                {
                    if (!Directory.Exists(Path.GetDirectoryName(localPath)))
                    {
                        Directory.CreateDirectory(Path.GetDirectoryName(localPath));
                    }
                    File.WriteAllBytes(localPath, uploadFileBytes);
                    Result.Url = savePath;
                    Result.State = UploadState.Success;
                }
                catch (Exception e)
                {
                    Result.State = UploadState.FileAccessError;
                    Result.ErrorMessage = e.Message;
                }
                finally
                {
                    WriteResult();
                }
            }
            else
            {
                var file = Request.Form.Files[UploadConfig.UploadFieldName];
                StreamReader reader = new StreamReader(file.OpenReadStream());
                string content = reader.ReadToEnd();
                uploadFileName = file.FileName;
                var savePath = PathFormatter.Format(uploadFileName, UploadConfig.PathFormat);
                var localPath = Environment.CurrentDirectory + "/wwwroot" + savePath;
                if (!CheckFileType(uploadFileName))
                {
                    Result.State = UploadState.TypeNotAllow;
                    WriteResult();
                    return;
                }
                if (!CheckFileSize(file.Length))
                {
                    Result.State = UploadState.SizeLimitExceed;
                    WriteResult();
                    return;
                }              
                try
                {
                    //查看该物理路径是否存在,如果不存在则新建对应文件夹
                    if (!Directory.Exists(Path.GetDirectoryName(localPath)))
                    {
                        Directory.CreateDirectory(Path.GetDirectoryName(localPath));
                    }
                    //File.WriteAllBytes(localPath, uploadFileBytes);
                    using (FileStream fs = System.IO.File.Create(localPath))
                    {
                        // 复制文件
                        file.CopyTo(fs);
                        // 清空缓冲区数据
                        fs.Flush();
                    }
                    Result.Url = savePath;
                    Result.State = UploadState.Success;
                }
                catch (Exception e)
                {
                    Result.State = UploadState.FileAccessError;
                    Result.ErrorMessage = e.Message;
                }
                finally
                {
                    WriteResult();
                }
            }

            
            
        }

        private void WriteResult()
        {
            this.WriteJson(new
            {
                state = GetStateMessage(Result.State),
                url = Result.Url,
                title = Result.OriginFileName,
                original = Result.OriginFileName,
                error = Result.ErrorMessage
            });
        }

        private string GetStateMessage(UploadState state)
        {
            switch (state)
            {
                case UploadState.Success:
                    return "SUCCESS";
                case UploadState.FileAccessError:
                    return "文件访问出错,请检查写入权限";
                case UploadState.SizeLimitExceed:
                    return "文件大小超出服务器限制";
                case UploadState.TypeNotAllow:
                    return "不允许的文件格式";
                case UploadState.NetworkError:
                    return "网络错误";
            }
            return "未知错误";
        }

        private bool CheckFileType(string filename)
        {
            var fileExtension = Path.GetExtension(filename).ToLower();
            return UploadConfig.AllowExtensions.Select(x => x.ToLower()).Contains(fileExtension);
        }

        private bool CheckFileSize(long size)
        {
            return size < UploadConfig.SizeLimit;
        }
    }

    public class UploadConfig
    {
        /// <summary>
        /// 文件命名规则
        /// </summary>
        public string PathFormat { get; set; }

        /// <summary>
        /// 上传表单域名称
        /// </summary>
        public string UploadFieldName { get; set; }

        /// <summary>
        /// 上传大小限制
        /// </summary>
        public int SizeLimit { get; set; }

        /// <summary>
        /// 上传允许的文件格式
        /// </summary>
        public string[] AllowExtensions { get; set; }

        /// <summary>
        /// 文件是否以 Base64 的形式上传
        /// </summary>
        public bool Base64 { get; set; }

        /// <summary>
        /// Base64 字符串所表示的文件名
        /// </summary>
        public string Base64Filename { get; set; }
    }

    public class UploadResult
    {
        public UploadState State { get; set; }
        public string Url { get; set; }
        public string OriginFileName { get; set; }

        public string ErrorMessage { get; set; }
    }

    public enum UploadState
    {
        Success = 0,
        SizeLimitExceed = -1,
        TypeNotAllow = -2,
        FileAccessError = -3,
        NetworkError = -4,
        Unknown = 1,
    }
    #endregion

    /// <summary>
    /// PathFormater 的摘要说明
    /// </summary>
    public static class PathFormatter
    {
        public static string Format(string originFileName, string pathFormat)
        {
            if (String.IsNullOrWhiteSpace(pathFormat))
            {
                pathFormat = "{filename}{rand:6}";
            }

            var invalidPattern = new Regex(@"[\\\/\:\*\?\042\<\>\|]");
            originFileName = invalidPattern.Replace(originFileName, "");

            string extension = Path.GetExtension(originFileName);
            string filename = Path.GetFileNameWithoutExtension(originFileName);

            pathFormat = pathFormat.Replace("{filename}", filename);
            pathFormat = new Regex(@"\{rand(\:?)(\d+)\}", RegexOptions.Compiled).Replace(pathFormat, new MatchEvaluator(delegate (Match match)
            {
                var digit = 6;
                if (match.Groups.Count > 2)
                {
                    digit = Convert.ToInt32(match.Groups[2].Value);
                }
                var rand = new Random();
                return rand.Next((int)Math.Pow(10, digit), (int)Math.Pow(10, digit + 1)).ToString();
            }));

            pathFormat = pathFormat.Replace("{time}", DateTime.Now.Ticks.ToString());
            pathFormat = pathFormat.Replace("{yyyy}", DateTime.Now.Year.ToString());
            pathFormat = pathFormat.Replace("{yy}", (DateTime.Now.Year % 100).ToString("D2"));
            pathFormat = pathFormat.Replace("{mm}", DateTime.Now.Month.ToString("D2"));
            pathFormat = pathFormat.Replace("{dd}", DateTime.Now.Day.ToString("D2"));
            pathFormat = pathFormat.Replace("{hh}", DateTime.Now.Hour.ToString("D2"));
            pathFormat = pathFormat.Replace("{ii}", DateTime.Now.Minute.ToString("D2"));
            pathFormat = pathFormat.Replace("{ss}", DateTime.Now.Second.ToString("D2"));

            return pathFormat + extension;
        }
    }

这样,百度富文本编辑器基本上图文操作就搞定了。如果还有不清楚的,可以加我微信:1057359832

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/159524.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【每日随笔】北京 MBA 学校选择

文章目录一、第一梯队二、第二梯队三、第三梯队四、MBA 的全日制和非全日制区别一、第一梯队 第一梯队 MBA : 招人非常严格 , 本科学历背景 , 薪资 , 工作年限 , 管理年限 , 要求很高 ; 二、第二梯队 第二梯队 MBA : 对外经贸大学 MBA 推荐 对外贸易 相关行业 , 对英语要求较高…

Dubbo高级特性

dubbo-admin安装 ●dubbo-admin管理平台&#xff0c;是图形化的服务管理页面 ●从注册中心中获取到所有的提供者 /消费者进行配置管理 ●路由规则、动态配置、服务降级、访问控制、权重调整、负载均衡等管理功能 ●dubbo- admin是一个前后端分离的项目。前端使用vue&#xff0…

[NeurIPS 2022] 消除视觉Transformer与卷积神经网络在小数据集上的差距

本文简要介绍NeurIPS 2022录用的论文“Bridging the Gap Between Vision Transformers and Convolutional Neural Networks on Small Datasets”的主要工作。该论文旨在通过增强视觉Transformer中的归纳偏置来提升其在小数据集上从随机初始化开始训练的识别性能。本文通过多种操…

M1pro 下通过Docker 安装 Redis

Mac M1pro 下通过Docker 安装 Redis 1、Redis镜像拉取&#xff0c;最新版本的镜像 启动Docker&#xff0c;打开终端输入命令&#xff1a;docker pull redis:latest 耐心等待拉取完毕 2、查看本地镜像&#xff0c;Redis是否下载成功 命令&#xff1a;docker images 3、运行启…

又一重要进展发布!OpenMMLab算法仓支持昇腾AI训练加速

近日&#xff0c;上海人工智能实验室的浦视开源算法体系&#xff08;OpenMMLab&#xff09;团队基于昇腾AI发布了MMDeploy 0.10.0版本&#xff0c;该版本已支持OpenMMLab算法仓库在昇腾异构计算架构CANN上的推理部署。而在最新发布的MMCV 1.7.0和MMEngine 0.3.0版本中&#xff…

Vue3——第十二章(Props)

一、Props 声明 一个组件需要显式声明它所接受的 props&#xff0c;这样 Vue 才能知道外部传入的哪些是 props&#xff0c;哪些是透传 attribute在使用 <script setup> 的单文件组件中&#xff0c;props 可以使用 defineProps() 宏来声明&#xff1a; 在没有使用 <sc…

【寒假每日一题】DAY.5 调整奇数偶数顺序

题目内容&#xff1a; 调整数组使奇数全部都位于偶数前面。题目&#xff1a;输入一个整数数组&#xff0c;实现一个函数&#xff0c;来调整该数组中数字的顺序使得数组中所有的奇数位于数组的前半部分&#xff0c;所有偶数位于数组的后半部分。思路&#xff1a; 第一步&#xf…

【Java并发编程] 线程八锁问题

文章目录1.共享会出现什么问题2. 什么是临界区3. synchronized解决方案4 线程八锁1.共享会出现什么问题 首先&#xff0c;我们先了解对某一资源共享会出现什么问题&#xff0c;然后怎么解决这个问题。 两个线程对初始值为 0 的静态变量一个做自增&#xff0c;一个做自减&…

STM32单片机CAN总线汽车自动会车灯远近光切换

实践制作DIY- GC0121-汽车自动会车灯 一、功能说明&#xff1a; 基于51单片机设计-汽车自动会车灯 功能介绍&#xff1a; OLED主控板&#xff1a;STM32F103C系列最小系统OLED显示3个按键&#xff08;开关、自动/手动、近光/远光&#xff09;CAN通讯模块 光敏LED板&#xff1a…

房产管理系统架构分析

数图互通高校房产管理系统是基于公司自主研发的FMCenterV5.0平台&#xff0c;是针对中国高校房产的管理特点和管理要求&#xff0c;研发的一套标准产品&#xff1b;通过在中国100多所高校的成功实施和迭代&#xff0c;形成了一套成熟、完善、全生命周期的房屋资源管理解决方案。…

你的示波器只能抓到5%的波形?

采样时间、死区时间和捕获时间 数字示波器捕获信号的过程是典型的“采集-处理-采集-处理”&#xff0c;如图1所示为数字示波器的采集原理&#xff0c;一个捕获周期由采样时间和处理时间&#xff08;死区时间&#xff09;组成&#xff0c;如图2所示。 图1 示波器采集原理图 采…

Redis String 命令与实战

在前面的文章中&#xff0c;我们了解了 Redis 的基本功能&#xff0c;通过源码方式安装了 Redis&#xff0c;并搭建了 Redis 的源码运行环境。接下来将进入 “Redis 的实战应用篇”&#xff0c;在这部分我们将重点介绍 Redis 核心命令的使用&#xff0c;主要包括 Redis 中 Stri…

磨金石教育摄影技能干货分享|摄影师镜头下生活的色彩

在生活中也有很多亮丽的色彩&#xff0c;生活在我们看起来是平凡的&#xff0c;但其实每个地方每个人都会有不同的风景。不同的文化&#xff0c;不同的地域&#xff0c;这些都足以构造出不同的色彩。下面就让我们跟随镜头看看世界各地人民多姿多彩的生活。1 生活的色彩这是西孟…

ASP .Net Core内置 Identity 简介 使用

一、简介 1、概况 ASP.NET Core Identity是一个成员身份系统&#xff0c;可将用户注册和登录功能添加到 ASP.NET Core Web UI。 成员身份系统处理身份验证和授权问题。 身份验证涉及你的身份。 授权涉及允许你进行的操作。 因此&#xff0c;身份验证是授权的先决条件。 ASP .N…

js判断 数组中是否存在形同元素

上例子 flag true; //假设不重复&#xff1b; let arr [{ settingName: 渠道客户订单, settingCode: A1 },{ settingName: 户订单, settingCode: A1 },];for(let i 0;i < arr.length-1;i){ //循环开始元素 for(let j i 1;j < arr.length;j){ //循环后续所有元素 …

Pandoc 多Markdown转单PDF

文章目录Pandoc 简介Pandoc 安装pandoc-latex-template字体安装Powershell 脚本Ubuntu PandocMarkdown 合并Pandoc 简介 Pandoc, 免费的文档转换器, 支持常见的各种文件格式的相互转换, 如Markdown, HTML, EPUB, LaTeX, docx, RTF, PDF 等. 本篇以Windows下的多Markdown转单P…

个性化脑机接口及应用

脑机接口&#xff08;BCI&#xff09;是一种变革传统人机交互的新型技术&#xff0c;用户的大脑是直接的控制信号源。在BCI转化为实际应用时&#xff0c;由于用户个体之间的感觉、知觉、表象与认知思维活动、脑结构与功能具有一定的差异&#xff0c;通用BCI难以满足不同个体的需…

国产linux操作系统——麒麟操作系统的来龙去脉(有下载地址,亲测可用)

文章目录1、linux操作系统2、国产操作系统3、麒麟操作系统4、引用1、linux操作系统 目前市场主流的linux操作系统分类大致如此&#xff0c;国产操作系统的麒麟操作系统&#xff0c;底层比较杂&#xff0c;所以单独一类。 2、国产操作系统 排名日期截止到2022.6。 这里提一下排…

基于java SSM的房屋租赁系统设计和实现

基于java SSM的房屋租赁系统设计和实现 博主介绍&#xff1a;5年java开发经验&#xff0c;专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 作者主页 超级帅帅吴 Java毕设项目精品实战案例《500套》 欢迎点赞 收藏 ⭐留言 文末获取源码联系方式 文…

ASO优化的两个渠道之推广+老用户维系

要想自己的APP在应用商城里获得较高的排名&#xff0c;提高用户的下载量&#xff0c;就要通过ASO优化来辅助完成。 &#xff08;一&#xff09;&#xff0c;ASO优化的排名因素——元数据的优化&#xff1a;1&#xff0c;icon图标。图片要直观和清晰地突出APP的内容&#xff0c…