Flask專案整合富文字編輯器UEditor
本文介紹如何在Flask專案中整合富文字編輯器UEditor,並實現檔案上傳、圖片上傳、視訊上傳及塗鴉功能。
UEditor簡介
UEditor是由百度「FEX前端研發團隊」開發的所見即所得富文字web編輯器,具有輕量,可定製,注重使用者體驗等特點,開源基於MIT協議,允許自由使用和修改程式碼。
由於1.4.2版本之後的版本與之前版本存在較大的差異,本文以1.4.3版本為藍本。
在Flask專案中加入UEditor
下載UEditor:
訪問UEditor首頁,下載1.4.3 PHP UTF-8版本的UEditor,並解壓到Flask應用程式的static
目錄。解壓之後的目錄結構是這樣的:
| static /
| | ueditor/
| | |+dialogs/
| | |+lang/
| | |+php/
| | |+themes/
| | |+third-party/
| | |-config.json
| | |-index.html
| | |-ueditor.all.js
| | |-ueditor.all.min.js
| | |-ueditor.config.js
| | |-ueditor.parse.js
| | |-ueditor.parse.min.js
+
表示目錄。
在專案中加入UEditor:
我們在Flask應用程式的templates
目錄新建一個index.html
檔案(可根據實際情況選擇檔名,或者把程式碼加入需要使用UEditor的檔案):
在head標籤加入下面幾行:
<script type="text/javascript" charset="utf-8" src="{{ url_for('static', filename='ueditor/ueditor.config.js') }}"></script>
<script type="text/javascript" charset="utf-8" src="{{ url_for('static', filename='ueditor/ueditor.all.min.js') }}"></script>
<!--建議手動加在語言,避免在ie下有時因為載入語言失敗導致編輯器載入失敗-->
<!--這裡載入的語言檔案會覆蓋你在配置專案裡新增的語言型別,比如你在配置專案裡配置的是英文,這裡載入的中文,那最後就是中文-->
<script type="text/javascript" charset="utf-8" src="{{ url_for('static', filename='ueditor/lang/zh-cn/zh-cn.js') }}"></script>
在body標籤加入:
<script id="editor" type="text/plain"></script>
<script type="text/javascript">
//例項化編輯器
//建議使用工廠方法getEditor建立和引用編輯器例項,如果在某個閉包下引用該編輯器,直接呼叫UE.getEditor('editor')就能拿到相關的例項
var ue = UE.getEditor('editor', {
serverUrl: "/upload/"
});
</script>
請求路徑配置:
UEditor 1.4.2+ 起,推薦使用統一的請求路徑,在部署好前端程式碼後,需要修改 ueditor.config.js
裡的
serverUrl
引數(或者初始化時指定,見上面的程式碼),改成 '/upload/'
。
UEditor初始化時,會向後端請求配置檔案,後端收到請求後返回JSON格式的配置檔案。具體實現參照後面的程式碼。
詳細配置內容參見文件。
建立Flask應用程式(app.py
):
# -*- coding: utf-8 -*-
# filename: app.py
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html')
@app.route('/upload/', methods=['GET', 'POST'])
def upload():
pass
if __name__ == '__main__':
app.run(debug=True)
應用程式執行之後,我們訪問 http://localhost:5000/
就可以看到UEditor編輯器了,上圖:
UEditor後端請求規範說明
與後臺通訊的功能列表:
- 上傳圖片
- 拖放圖片上傳、貼上板圖片上傳
- word文件圖片轉存
- 截圖工具上傳
- 上傳塗鴉
- 上傳視訊
- 上傳附件
- 線上圖片管理
- 貼上轉存遠端圖片
統一請求格式說明:
- 前端請求通過唯一的後臺檔案
/upload/
處理前端的請求 /upload/
通過GET上的action
引數,判斷是什麼型別的請求- 省去不必要的請求,去除塗鴉新增背景的請求,用前端FileReader讀取本地圖片代替
- 請求返回資料的格式,常規返回json字串,資料包含state屬性(成功時返回'SUCCESS',錯誤時返回錯誤資訊)。
- 請求支援jsonp請求格式,當請求有通過GET方式傳callback的引數時,返回json資料前後加上括號,再在前面加上callback的值,格式類似這樣:
cb({"key": "value"})
Flask實現後端請求
獲取配置資訊
由於介面升級,編輯器初始化時,首先會向後端請求配置資訊,後端收到請求後,返
回相應的配置資訊即可。
請求引數:
GET {"action": "config"}
POST "upfile": File Data
返回格式:
// 需要支援callback引數,返回jsonp格式
{
"imageUrl": "http://localhost/ueditor/php/controller.php?action=uploadimage",
"imagePath": "/ueditor/php/",
"imageFieldName": "upfile",
"imageMaxSize": 2048,
"imageAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"]
}
主要功能程式碼:
@app.route('/upload/', methods=['GET', 'POST'])
def upload():
action = request.args.get('action')
# 解析JSON格式的配置檔案
# 這裡使用PHP版本自帶的config.json檔案
with open(os.path.join(app.static_folder, 'ueditor', 'php',
'config.json')) as fp:
try:
# 刪除 `/**/` 之間的註釋
CONFIG = json.loads(re.sub(r'\/\*.*\*\/', '', fp.read()))
except:
CONFIG = {}
if action == 'config':
# 初始化時,返回配置檔案給客戶端
result = CONFIG
return json.dumps(result)
檔案、視訊、圖片上傳
圖片上傳包括:本地圖片上傳、拖拽圖片上傳、貼上板圖片上傳。
這些功能實現的方法是一樣的,所以放到一起來講。上傳的檔案可用request.files['upfile']
獲取。
請求引數:
GET {"action": "uploadimage"}
POST "upfile": File Data
action說明:
- uploadimage 上傳圖片
- uploadvideo 上傳視訊檔案
- uploadfile 上傳附件(檔案)
返回格式:
{
"state": "SUCCESS",
"url": "upload/demo.jpg",
"title": "demo.jpg",
"original": "demo.jpg"
}
主要功能程式碼:
@app.route('/upload/', methods=['GET', 'POST'])
def upload():
result = {}
action = request.args.get('action')
if action in ('uploadimage', 'uploadvideo', 'uploadfile'):
upfile = request.files['upfile'] # 這個表單名稱以配置檔案為準
# upfile 為 FileStorage 物件
# 這裡儲存檔案並返回相應的URL
upfile.save(filename_to_save)
result = {
"state": "SUCCESS",
"url": "upload/demo.jpg",
"title": "demo.jpg",
"original": "demo.jpg"
}
return json.dumps(result)
塗鴉功能
塗鴉功能上傳經過BASE64編碼的圖片(一般為PNG格式),可用request.form['upfile']
獲取,後端收到之後需要先解碼,再儲存。
請求引數:
GET {"action": "uploadscrawl"}
POST "content": Base64 Data
返回格式:
{
"state": "SUCCESS",
"url": "upload/demo.jpg",
"title": "demo.jpg",
"original": "demo.jpg"
}
主要功能程式碼:
@app.route('/upload/', methods=['GET', 'POST'])
def upload():
result = {}
action = request.args.get('action')
if action in ('uploadscrawl'):
base64data = request.form['upfile'] # 這個表單名稱以配置檔案為準
img = base64.b64decode(base64data)
# 這裡儲存檔案並返回相應的URL
with open(filename_to_save, 'wb') as fp:
fp.write(img)
result = {
"state": "SUCCESS",
"url": "upload/demo.jpg",
"title": "demo.jpg",
"original": "demo.jpg"
}
return json.dumps(result)
遠端抓圖
遠端抓圖主要是把站外的圖片儲存到本地或者指定的圖片伺服器。
當複製貼上其他網站的網頁的圖片時,會觸發遠端抓圖功能。
遠端圖片列表可通過request.form.getlist('source[]')
獲取。這裡暫時不清楚是
什麼原因,為什麼request.form.getlist('source')
為空。
核心思路:遍歷遠端圖片列表,通過urllib把圖片下載並儲存,下載完成之後按照格
式返回結果。
請求引數:
GET {
"action": "catchimage",
"source": [
"http://a.com/1.jpg",
"http://a.com/2.jpg"
]
}
返回格式:
// 需要支援callback引數,返回jsonp格式
// list項的state屬性和最外面的state格式一致
{
"state": "SUCCESS",
"list": [{
"url": "upload/1.jpg",
"source": "http://b.com/2.jpg",
"state": "SUCCESS"
}, {
"url": "upload/2.jpg",
"source": "http://b.com/2.jpg",
"state": "SUCCESS"
}, ]
}
完整DEMO
實現了圖片上傳、附件上傳、視訊上傳、塗鴉、遠端抓圖等功能。