UEditor 之初体验后记
本文初稿写于 3 年前,近期重新编辑整理,并进一步完善补充而成。
1、ueditor 基本介绍
1.1、关于 ueditor
ueditor是由百度web前端研发部开发所见即所得富文本web编辑器,具有轻量,可定制,注重用户体验等特点,开源基于mit协议,允许*使用和修改代码。
上面这句话出自 ueditor 官方。在我看来,ueditor 的核心特点就是:产自大厂、开源免费、功能全面(相当全)、体验较为切合国人习惯。想了解 ueditor 的更多信息,可参考以下几个链接:
另外,ueditor 官方还提供了一个 mini 版,名字叫 umeditor。说是为了满足广大门户网站对于简单发帖框,或者回复框需求所定制的版本。主要改进点在加载速度和加载失败率上,且功能与 ueditor 也略有不同,具体可参考 umeditor 的 github。
1.2、ueditor 现状
ueditor 的最新版本是 v1.4.3.3,umeditor 的最新版本是 v1.2.3。最后一次发布都在 2016 年下半年,都快 3 年没更新了。不过基本功能该有的也都有,且社区也比较认同和推崇,有不少人或组织都提供了特色的改进版或增强版,官方也偶有跟进。
综合来看,目前要在国内做相对复杂的资讯发布或留言功能,ueditor/umeditor 依然是最好的选择之一。
2、ueditor 简单使用
2.1、将 ueditor 源码集成到项目中
如果你要在后端项目中集成 ueditor,那么直接下载对应语言版本的源码,解压之后拷贝到项目中即可。有两点需要注意:
- 1、官方只提供了 php、asp、asp.net、jsp 四个版本,社区里有人提供了 note.js、python 等语言的版本。
- 2、官方说提供的所有后端代码都仅为 demo 作用,切不可直接用到生产环境中。平心而论,asp.net 版的后端代码写的确实水,不过前端能写出这些后端代码就已经很牛掰了,我是把用到的那部分代码从头到尾改了一遍才用到生产环境中的。
如果你要在前端项目中集成 ueditor,那就看你需不需要上传图片等后端功能了。如果不需要,那么直接拷贝到前端项目中即可。但如果需要,那就得确保跑前端的 web 服务器能解析对应的后端代码了。
当然,如果你把 ueditor 单独部署到一个支持后端的 web 服务器上也是可行的。另外,集成 umeditor 的方法与集成 ueditor 方法完全一样。
2.2、让 ueditor 的 ui 呈现在页面中
1、首先,需要在页面中引入 ueditor 的 3 个 js 文件,示例如下:
<!-- 编辑器的配置文件,前端配置都在这个文件中,注释十分丰富 --> <script type="text/javascript" charset="utf-8" src="/ueditor-1.4.3/ueditor.config.js"></script> <!-- 编辑器的源码文件 --> <script type="text/javascript" charset="utf-8" src="/ueditor-1.4.3/ueditor.all.min.js"></script> <!-- 编辑器的中文语言包 --> <script type="text/javascript" charset="utf-8" src="/ueditor-1.4.3/lang/zh-cn/zh-cn.js"></script>
2、然后,在页面中需要呈现 ueditor 的地方放置如下“占位符”代码(注意给个 id,下一步要用):
<!-- 编辑器的容器 --> <script id="editor" type="text/plain" style="width:800px; height:300px;"></script>
3、最后,通过一句实例化编辑器的代码来获得编辑器实例(页面运行起来时 ui 就会呈现出来):
$(function () { var ue = ue.geteditor("editor"); // 创建编辑器实例(这里的 editor 就是上一步中的 id) });
得到编辑器实例对象之后,就可以通过它来调用 ueditor 的哪些 api 了。具体有哪些 api 可用,参见 ueditor api。
2.3、用 ueditor 的过程中遇到的两个坑
1、坑一,获取内容可以而设置内容却报错。
我用getcontent
获取编辑器的内容并存入数据库,然后把存到数据库中的内容用setcontent
赋给编辑器。结果运行起来发现保存入库可以,而打开编辑页面直接就报错了,编辑器也没显示出来。
后来发现这个是因为编辑器还没准备好,所以就不能赋值,只需要把赋值操作放到ready
之后即可,示例代码如下:
ue.addlistener("ready", function () { ue.setcontent("@model.content"); // 等编辑器准备好之后再赋值,否则报错 });
为了写这篇文章,我尝试了重现那个错误,结果编辑器又显示出来了,但依然会报错,错误消息是“uncaught typeerror: cannot set property 'innerhtml' of undefined”。
从某种程度上说,这个问题并不算是坑。因为官方手册中就有相关说明和建议——“对编辑器的操作最好在编辑器ready之后再做”,不过我这人特别怕麻烦,凡是能凭猜测搞定的就不愿细看文档,所以第一次用的时候就掉坑了。
2、坑二,编辑器内显示的是的 html,而不是文本内容。
一开始还怀疑这会不会是 ueditor 的 bug,直到把这个问题解决之后,反过来想才发现这里面其实隐含了一个容易被忽略的“常识”,那就是网页的模版引擎一般都会编码字符串,比如我曾用过的 webforms、nvelocity 和 razorengine 都是这样。
换句话说,这时候编辑器拿到的是经过编码之后 html,也就是说只要我们能确保编辑器拿到的是编码前的 html 就行了。当然一开始我还没想到是这个原因,于是我的解决办法是根据曾使用其它编辑器的经验试出来的,就是直接把内容放到script
标签中,示例代码如下:
<script id="editor" type="text/plain" style="width:800px;height:300px;"> @webtools.razorhelper.raw(model.segment.note) </script>
在我意识到这个问题的始作俑者是网页模版引擎而不是 ueditor 的时候,我做了如下测试:
ue.addlistener("ready", function () { editor.setcontent("@webtools.razorhelper.raw(model.segment.note)"); });
果然也是 ok 的,这也进一步证明了我的猜想是正确的!
2.4、将 ueditor 中的图片上传到云服务器上
由于 ueditor 默认是将图片上传到网站根目录下的一个子文件夹中,如果是企业内部的信息系统,这么做也还行,但如果是互联网项目,这种做法就显得既不安全、也不经济的了,最好还是上传到云服务器上。
要把 ueditor 中的图片上传到云服务器上,只需要修改后端代码的上传逻辑即可。我做过用 asp.net 把 ueditor 1.4.3 中的图片上传到 又拍云 uss 和把 umeditor 1.2.2 中的图片上传到 阿里云 oss,其实思路是一样的。
ueditor 的 asp.net 核心上传逻辑在uploadhandler
类的process
方法中,将上传图片到本地的那部分代码替换成如下示例代码即可。
try { // 校验文件类型、文件大小等...... string filemd5 = stringsecurity.getmd5(uploadfilebytes); // 用文件的 md5 值做文件名 string filename = filemd5 + path.getextension(uploadfilename); string filepath = $"/images/{datetime.now.tostring("yymmdd")}/{filename}"; // 调用又拍云的 sdk 来上传文件 upyun upyun = new upyun("bucketname", "username", "password"); upyun.setcontentmd5(filemd5); bool upyunresult = upyun.writefile(filepath, uploadfilebytes, true); // ...... } catch (exception e) { logger.error("文件上传失败!", e); // ...... }
umeditor 的 asp.net 核心上传逻辑在uploader
类的upfile
方法中,将上传图片到本地的那部分代码替换成如下示例代码即可。
try { // 校验文件类型、文件大小等...... string filename = $"{guidhelper.lowerpurestring}.{getfileext()}"; string filepath = $"images/{datetime.now.tostring("yymmdd")}/{filename}"; // 调用阿里云的 sdk 来上传文件 var client = new ossclient(srcpoint, accesskeyid, accesskeysecret, new aliyun.oss.common.clientconfiguration() { iscname = true }); var putresult = client.putobject(srcbucket, filepath, uploadfile.inputstream); // ...... var uri = client.generatepresigneduri(srcbucket, filepath); url = uri.getleftpart(uripartial.path); // 将文件路径赋值给编辑器引用的变量 } catch (exception e) { logger.error("文件上传失败!", e); // ...... }
可能你看到本文时,又拍云和阿里云的云存储 sdk 已经做了较大改动,这里附上二者的 github 链接:
3、web 编辑器杂谈
3.1、我与 ueditor 的曲折历程
2016 年初,我基于学习的目的,业余做了一个带新闻发布功能的网站。在这之前,我曾先后用过 freetextbox 和 fckeditor(已更名为 ckeditor),印象中都还不错,但也都有着这样或者那样的问题,比如 ckeditor 中空格变问号的问题。
我上网搜了一下,发现大家对 ueditor 的评价还不错,于是决定 web 编辑器就用 ueditor,由于是第一次用,过程相对曲折。做完新闻发布功能之后,就顺带记录了一下,也就是本文初稿。
两年之后,也就是去年,公司要做个带资讯发布功能的媒体网站,在我的建议下,最终选用了 umeditor。但整个团队除我之外都没用过,尤其是那几个前端,连富文本编辑器是啥都不知道,最后就由我负责带领前端来做这块儿的功能。
因为这次做的是实际项目,公司的编辑们都在用,后台的 ui 框架也由 jquery 版的 easyui 变成了 react 版的 ant design,所以遇到的细节问题也比较多。其中对编辑器的各种配置和后端改造,都是由我统一解决好再跟前端对接的。
又过了一年,也就是本月初,我在整理资料时再次看到了本文初稿。瞬间就想起我去年用 umeditor 的过程中也做过一些记录,然后就想着干脆把两次的记录整合起来,结果怎么都找不到去年的记录,只好作罢。也许还留在那家公司的电脑里吧!
3.2、ckeditor 空格变问号的原因及解决办法
经查,导致该问题的根本原因是编码转换。在 utf-8 里有一个特殊的编码0xc2 0xa0
,转换成字符的时候,表现为一个空格,跟普通的半角空格一样,不同的是它的宽度不会被压缩,因此常被用来做网页排版。而在 gb2312、unicode 等字符集中却没有这个编码,因此如果简单地进行编码转换,这个编码就会被替换成问号。
前些年在实际项目中还遇到过更奇葩的情况,文章保存之后,内容中的问号就全都没了。后来发现是别人也遇到了空格变问号的问题,但选错了解决方案,他是直接把问号又替换成空格,结果正常的问号也被毙掉了。
正确的做法是,用 utf-8 格式的编码进行替换,把那个特殊的空格替换为普通的空格,如果是 html 字符串,那就替换为
。c# 代码替换 html 字符串的示例如下:
byte[] space = new byte[]{0xc2,0xa0}; string utfspace = encoding.getencoding("utf-8").getstring(space); htmlstr = htmlstr.replace(utfspace," ");
注意:在替换之前不能进行编码转换,一定要继续使用 utf-8 编码。如果已经转换成其它编码,那就彻底没救了,因为这时候错误的问号和正常的问号之间已经没有分别了。
本文链接:
版权声明:本文为博客园博主 原创,作者保留署名权!欢迎通过转载、演绎或其它传播方式来使用本文,但必须在明显位置给出作者署名和本文链接!个人博客,能力有限,若有不当之处,敬请批评指正,谢谢!