效果圖
前言
據我了解,這是一款基于bootstrap的富文本編輯器,比較喜歡的它的樣式風格和圖檔上傳的功能。
問題1:
它預設的圖檔上傳,是把圖檔轉成base64編碼并送出給後端。這顯然不是我們想要的,我們希望圖檔以檔案形式送出給後端儲存,後端傳回其儲存的路徑。
問題2:
圖檔異步上傳時,沒有進度顯示。如果上傳動态圖等較大的圖檔,使用者體驗不是很好。為此,我使用一款基于bootstrap的模态框插件 BootBox.js (https://www.bootboxjs.cn/)來顯示上傳進度條。
踩坑
1、bootstrap,bootbox, summernote相關依賴引入,略...
2、summernote的API可能不同版本之間有差異,這裡隻提供重寫圖檔上傳和顯示上傳進度條的思路,summernote具體API參照官網文檔
3、在伺服器部署環境下測試:
(1)有時候發現圖檔插入位置錯誤,并沒有成功插入到編輯框中,但在本地測試沒發現。原因未知。
(2)為什麼進度條滿了之後,要等一會進度條對話框才消失?
上傳進度,是指前端已經發送出去的位元組數,後端完全接收之後。會把臨時檔案移動到指定目錄,并往資料庫中插入資料。業務層面的操作需要耗時。是以,進度條滿了,代表前端已經把所有位元組發送出去。從完全發送完畢到得到響應的中間有一段時間差。當得到響應後,進度條對話框才隐藏。
(3)為什麼進度條對話框隐藏之後,要等一會圖檔才插入到編輯框中?
summernote中插入圖檔的操作是異步的。是以沒有等到插入圖檔完成,進度條對話框就被關閉了。圖檔被插入到編輯框後,要根據網絡URL來加載圖檔,測試發現是完全加載圖檔後才插入到編輯框中顯示出來。如果伺服器帶寬小(我用的學生伺服器),較大的圖檔加載會比較慢。
代碼
<script>
$(function() {
var $summernote = $('#summernote').summernote({
height: 420,
focus: true,
toolbar: [
['style', ['style']],
['font', ['bold', 'italic', 'underline', 'clear']],
['fontname', ['fontname']],
['fontsize', ['fontsize']],
['color', ['color']],
['para', ['ul', 'ol', 'paragraph']],
['height', ['height']],
['table', ['table']],
['insert', ['link', 'picture', 'video']],
['view', ['fullscreen', 'codeview']],
['help', ['help']]
],
// 複寫圖檔上傳方法
onImageUpload: function (files, editor, $editable) {
sendFile(files[0], editor, $editable);
}
});
//ajax上傳圖檔
function sendFile(file, editor, $editable) {
if (file == null) {
// 取消或關閉了檔案選擇對話框
return;
}
console.log(editor);
console.log($editable);
var val = 0; // 進度。百分比
var totalBytes = file.size; // 檔案的總位元組數
console.log(totalBytes);
var formData = new FormData();
formData.append("file", file);
// 顯示進度對話框
showProgressDialog();
var uploadAjax = $.ajax({
url: "圖檔上傳的接口路徑",
type: 'POST',
data: formData,
cache: false,
contentType: false,
processData: false,
xhr: function() {
//擷取原生的xhr對象
var xhr = $.ajaxSettings.xhr();
if (xhr.upload) {
//添加 progress 事件監聽
//console.log(xhr.upload);
xhr.upload.onprogress = function(e) {
// e.loaded 已經加載的位元組數
val = (int) (e.loaded / totalBytes * 100);
if (val > 100) {
val = 100;
}
// 更新進度條的進度
$('#progressBar').css({
width: val.toFixed(2) + '%'
});
$('#progressBar').html(val.toFixed(2) + '%');
};
xhr.upload.onabort = function() {
// 取消上傳的回調
};
}
return xhr;
},
// ajax請求成功的回調
success: function (data) {
console.log(data);
if (data['result'] === true) {
//console.log($editable);
// 異步将圖檔插入到編輯框中
editor.insertImage($editable, "__public__/" + data['save_path']);
//$summernote.summernote('insertImage', data['save_path']);
} else {
alert(data['error']);
}
// 關閉對話框
bootbox.hideAll();
}
});
function showProgressDialog() {
var html =
"<div class='progress'><div id='progressBar' class='progress-bar' role='progressbar' style='min-width: 2em;'>" + (val + '%') + "</div></div>";
bootbox.dialog({
title: '正在上傳...',
message: html,
size: 'large',
onEscape: false,
backdrop: false,
buttons: {
cancel: {
label: '取消',
className: 'btn btn-outline-danger',
callback: function(){
// 中斷ajax請求
if (uploadAjax != null) {
//console.log(uploadAjax);
uploadAjax.abort();
}
// 關閉對話框
bootbox.hideAll();
}
}
}
});
}
}
});
</script>