UEditor 的核心特點就是:產自大廠、開源免費、功能全面(相當全)、體驗較為切合國人習慣。只需要修改相應的後端代碼,即可把 UEditor/UMeditor 中的圖片上傳到諸如又拍雲 USS 或阿裡雲 OSS 等雲存儲伺服器上,既安全又經濟。 ...
本文初稿寫於 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 編碼。如果已經轉換成其它編碼,那就徹底沒救了,因為這時候錯誤的問號和正常的問號之間已經沒有分別了。
本文鏈接:http://www.cnblogs.com/hanzongze/p/js-ueditor.html
版權聲明:本文為博客園博主 韓宗澤 原創,作者保留署名權!歡迎通過轉載、演繹或其它傳播方式來使用本文,但必須在明顯位置給出作者署名和本文鏈接!個人博客,能力有限,若有不當之處,敬請批評指正,謝謝!