????????接到這個需求的時候有點詫異和迷茫尖淘,后面經(jīng)過自己的一步一步摸索終于實現(xiàn)了這個讓人頭疼的需求奕锌。客戶需求:從第三方(秀米編輯器)復(fù)制粘貼圖文保留圖文樣式村生,并且圖片批量上傳至本地文件夾惊暴,并在小程序端顯示。前端是vue趁桃,后端是java語言辽话。
? ? ? ? 這個功能是實現(xiàn)我試了3個富文本,分別是quillEditor卫病,tinymce油啤,vue-html5-editor。
????????最后用vue-html5-editor這個富文本實現(xiàn)了蟀苛,vue-html5-editor富文本從第三方復(fù)制過來時可以保留第三方的所有樣式益咬,包括文字樣式,圖片樣式帜平。思路:復(fù)制過來圖片批量上傳是在后臺(JAVA)進行處理的幽告,后臺可以直接用正則表達(dá)式截取網(wǎng)絡(luò)圖片或者Base64圖片上傳至本地文件夾然后顯示在小程序端比庄。
? ? ? ? 先介紹一下quillEditor這個富文本蜕劝,quillEditor該富文本只能實現(xiàn)單個圖片上傳酪惭,從第三方復(fù)制黏貼過來上傳無效液南,親測鹃唯。
? ??????tinymce可以使用powerpaste(收費)插件進行圖片批量上傳禀晓,但是我公司做的是一個小項目达椰,老板也拒絕付費去購買該插件友绝。網(wǎng)上其實也可以找到powerpaste插件,可以去網(wǎng)盤直接下載芋绸,但是又遇到問題從網(wǎng)盤下載的powerpaste(不收費插件)配Tinymce4.x就會很多地方不適應(yīng)的地方媒殉,該版本的兼容性肯定不行,會導(dǎo)致圖片復(fù)制過來是空白的問題摔敛,然后又放棄了這個富文本廷蓉。
? ??????vue-html5-editor富文本雖然是個html5的富文本,但是從第三方復(fù)制過來的圖文是可以保留樣式的马昙,然后百度搜索該富文本是否有批量上傳圖片的屬性桃犬,根本沒有找到,然后自己轉(zhuǎn)換了想法行楞,決定在前端點保存時把圖片全部都都轉(zhuǎn)成base64格式攒暇,轉(zhuǎn)完之后存進數(shù)據(jù)庫里發(fā)現(xiàn)數(shù)據(jù)量太大(5M,10M)子房,在小程序端渲染速率太慢了形用。這個想法也放棄了。
? ? ? ? 最后靈機一動發(fā)現(xiàn)可以把網(wǎng)絡(luò)圖片或者bsae64的圖片直接在后臺進行上傳证杭。不多說了田度,上代碼。
?步驟一: 前端(vue):
在頁面引入
<vue-html5-editor class="coursesuggest" :content="activityForm.activityContent" @change="updateData"></vue-html5-editor>
步驟二:在main.js引入
let opt = {
// 全局組件名稱解愤,使用new VueHtml5Editor(options)時該選項無效
? name:"vue-html5-editor",
// 是否顯示模塊名稱镇饺,開啟的話會在工具欄的圖標(biāo)后臺直接顯示名稱
? showModuleName:true,
// 自定義各個圖標(biāo)的class,默認(rèn)使用的是font-awesome提供的圖標(biāo)
? icons: {
text:"fa fa-pencil",
color:"fa fa-paint-brush",
font:"fa fa-font",
align:"fa fa-align-justify",
list:"fa fa-list",
link:"fa fa-chain",
unlink:"fa fa-chain-broken",
tabulation:"fa fa-table",
image:"fa fa-file-image-o",
hr:"fa fa-minus",
eraser:"fa fa-eraser",
undo:"fa-undo fa",
"full-screen":"fa fa-arrows-alt",
info:"fa fa-info",
},
// 配置圖片模塊
? image: {
// 文件最大體積送讲,單位字節(jié)
? ? sizeLimit:512 *1024 *10,
// 上傳參數(shù),默認(rèn)把圖片轉(zhuǎn)為base64而不上傳
// upload config,default null and convert image to base64
? ? upload: {
// url: 'https://test.xiujianshen.com/media/upload',
? ? ? url:null,
headers: {
},
params: {
},
fieldName:'file'
? ? },
// 壓縮參數(shù),默認(rèn)使用localResizeIMG進行壓縮,設(shè)置為null禁止壓縮
// width和height是文件的最大寬高
? ? compress: {
width:300,
height:null,
quality:80
? ? },
// 響應(yīng)數(shù)據(jù)處理,最終返回圖片鏈接
? ? uploadHandler(responseText){
console.log(JSON.parse(responseText));
//? ? ? default accept json data like? {ok:false,msg:"unexpected"} or {ok:true,data:"image url"}
? ? ? var json =JSON.parse(responseText);
if(json.code ==0){
return json.data;
}else{
alert(json.message)
}
}
},
// 語言奸笤,內(nèi)建的有英文(en-us)和中文(zh-cn)
? language:"zh-cn",
// 自定義語言
? i18n: {
"zh-cn": {
"align":"對齊方式",
"image":"圖片",
"list":"列表",
"link":"鏈接",
"unlink":"去除鏈接",
"table":"表格",
"font":"文字",
"full screen":"全屏",
"text":"排版",
"eraser":"格式清除",
"info":"關(guān)于",
"color":"顏色",
"please enter a url":"請輸入地址",
"create link":"創(chuàng)建鏈接",
"bold":"加粗",
"italic":"傾斜",
"underline":"下劃線",
"strike through":"刪除線",
"subscript":"上標(biāo)",
"superscript":"下標(biāo)",
"heading":"標(biāo)題",
"font name":"字體",
"font size":"文字大小",
"left justify":"左對齊",
"center justify":"居中",
"right justify":"右對齊",
"ordered list":"有序列表",
"unordered list":"無序列表",
"fore color":"前景色",
"background color":"背景色",
"row count":"行數(shù)",
"column count":"列數(shù)",
"save":"確定",
"upload":"上傳",
"progress":"進度",
"unknown":"未知",
"please wait":"請稍等",
"error":"錯誤",
"abort":"中斷",
"reset":"重置"
? ? }
},
// 隱藏不想要顯示出來的模塊
? hiddenModules: [],
// 自定義要顯示的模塊,并控制順序
? visibleModules: [
"text",
"color",
"font",
"align",
"list",
"link",
"unlink",
"tabulation",
"image",
"hr",
"eraser",
"undo",
"full-screen",
"info",
],
// 擴展模塊哼鬓,具體可以參考examples或查看源碼
// extended modules
? modules: {
//omit,reference to source code of build-in modules
? }
};
Vue.use(VueHtml5Editor,opt);
步驟三:前臺頁面點提交后把富文本的全部數(shù)據(jù)都傳到后臺监右,后臺代碼如下
String regex ="src=['\"](.*?)['\"]";//正則表達(dá)式來匹配src屬性
Pattern pattern = Pattern.compile(regex);//使用正則獲取富文本里的所有圖片
Matcher m = pattern.matcher(activity.getActivityContent());//傳入富文本內(nèi)容進行格式化
StringBuffer sb =new StringBuffer();//new一個StringBuffer
while( m.find())
{
String newUrl="";
String url = m.group(1);//?外鏈URL
//單個圖片上傳時是base64
? ? if(url.indexOf("data") != -1){
//去掉base64字符串的開頭部分
? ? ? ? String base64Url = url.substring(url.indexOf(",")+1);
newUrl=GenerateImage(base64Url);
}
//復(fù)制上傳是網(wǎng)絡(luò)圖片
? ? else {
newUrl = richImage(url);//?本地化
? ? }
String newSrc = String.format(" src='%s' ", newUrl);//?新的src屬性
? ? m.appendReplacement(sb, newSrc);//?替換回去
}
m.appendTail(sb);
String ActivityContent = sb.toString();//獲取替換后的富文本
上面分別把base64的圖片和網(wǎng)絡(luò)圖片上傳到了本地,
base64上傳代碼如下
/**
* base64轉(zhuǎn)圖片上傳至本地文件夾
* @param base64str base64碼
* @return
*/
public String GenerateImage(String base64str)throws Exception{
BASE64Decoder decoder =new BASE64Decoder();
//Base64解碼
? ? byte[] b = decoder.decodeBuffer(base64str);
for (int i =0; i < b.length; ++i) {
//調(diào)整異常數(shù)據(jù)
? ? ? ? if (b[i] <0) {
b[i] +=256;
}
}
int x = (int) (Math.random() *1000);
String filedata = dates();
SimpleDateFormat df =new SimpleDateFormat("yyyy-MM-dd");//設(shè)置日期格式
? ? String date=df.format(new Date());
//new一個文件對象用來保存圖片魄宏,默認(rèn)保存當(dāng)前工程根目錄
? ? String realPath = SpringConfig.fileRootPath + SpringConfig.activityEditorImage+date;
File imageFile =new File(realPath);
if (imageFile.exists()) {
}else {
imageFile.mkdir();
}
String realPath1 = SpringConfig.fileRootPath + SpringConfig.activityEditorImage + date+"/" + x + filedata +".jpeg";
//生成jpeg圖片
? ? OutputStream out =new FileOutputStream(realPath1);
out.write(b);
out.flush();
out.close();
//返回本地化后的圖片路徑 SpringConfig.fileRootWeb+
? ? String outFielPath ="/static"+SpringConfig.activityEditorImage +"/"+ date+"/"? + x + filedata +".jpeg";
return outFielPath;
}
網(wǎng)絡(luò)圖片上傳代碼如下:
/**
* 秀米圖片轉(zhuǎn)圖片上傳至本地文件夾
* @param imgOldUrl
* @return
*/
public String richImage(String imgOldUrl)throws Exception{
//new一個URL對象
? ? URL url =new URL(imgOldUrl);
//打開鏈接
? ? HttpURLConnection conn = (HttpURLConnection)url.openConnection();
//設(shè)置請求方式為"GET"
? ? conn.setRequestMethod("GET");
//超時響應(yīng)時間為5秒
? ? conn.setConnectTimeout(5 *1000);
//通過輸入流獲取圖片數(shù)據(jù)
? ? InputStream inStream = conn.getInputStream();
//得到圖片的二進制數(shù)據(jù)秸侣,以二進制封裝得到數(shù)據(jù)存筏,具有通用性
? ? byte[] data =this.readInputStream(inStream);
int x = (int) (Math.random() *1000);
String filedata = dates();
SimpleDateFormat df =new SimpleDateFormat("yyyy-MM-dd");//設(shè)置日期格式
? ? String date=df.format(new Date());
//new一個文件對象用來保存圖片宠互,默認(rèn)保存當(dāng)前工程根目錄
? ? String realPath = SpringConfig.fileRootPath + SpringConfig.activityEditorImage+date;
File imageFile =new File(realPath);
if (imageFile.exists()) {
}else {
imageFile.mkdir();
}
String realPath1 = SpringConfig.fileRootPath + SpringConfig.activityEditorImage + date+"/" + x + filedata +".jpeg";
File imageFile1 =new File(realPath1);
//創(chuàng)建輸出流
? ? FileOutputStream outStream =new FileOutputStream(imageFile1);
//寫入數(shù)據(jù)
? ? outStream.write(data);
//關(guān)閉輸出流
? ? outStream.close();
//返回本地化后的圖片路徑 SpringConfig.fileRootWeb+
? ? String outFielPath ="/static"+SpringConfig.activityEditorImage +"/"+ date+"/"? + x + filedata +".jpeg";
return outFielPath;
}
public byte[] readInputStream(InputStream inStream)throws Exception{
ByteArrayOutputStream outStream =new ByteArrayOutputStream();
//創(chuàng)建一個Buffer字符串
? ? byte[] buffer =new byte[1024];
//每次讀取的字符串長度,如果為-1椭坚,代表全部讀取完畢
? ? int len =0;
//使用一個輸入流從buffer里把數(shù)據(jù)讀取出來
? ? while( (len=inStream.read(buffer)) != -1 ){
//用輸出流往buffer里寫入數(shù)據(jù)予跌,中間參數(shù)代表從哪個位置開始讀,len代表讀取的長度
? ? ? ? outStream.write(buffer,0, len);
}
//關(guān)閉輸入流
? ? inStream.close();
//把outStream里的數(shù)據(jù)寫入內(nèi)存
? ? return outStream.toByteArray();
}
以上步驟就分別把富文本的普通批量上傳了善茎,可以看到文件夾里有復(fù)制過來上傳的大量圖片
富文本批量上傳的功能也就實現(xiàn)了券册,其實其他2個富文本也可以用后臺上傳圖片的方式處理,只是這2個富文本實現(xiàn)不了保留第三方復(fù)制過來的圖文的格式。所以我最終選擇了vue-html5-editor烁焙。歡迎大家投稿航邢,第一次寫簡書文檔,菜鳥程序員飛真順獻上骄蝇。V:yqf822547775