在第二篇文章中,介绍过如何进行站外内容的复制粘贴,当时将html元素都转换为带段落的文字,并且将图片等其它标签直接去掉了。
这样做,对用户的使用并不友好,用户想把站外的文章连文字一起粘贴到本站的过程,被割裂了,所以,要想办法将站外图片一并粘贴过来。
在粘贴的时候,我们获得的剪贴板的内容其实是一段html字符串.
首先我们要将html字符串中的图片元素的src获得到,然后想办法将图片的url转存到我们自己的文件服务器上。
这里我们使用了七牛的url转存服务,简单来说,这个服务的输入就是一个第三方的图片url,返回就是,这个图片被转存到七牛我们自己账户下面后的url。真是轻松加愉快。
但是要注意的是,这个过程可能会比较慢,也会有失败的可能性,所以要做好特殊情况的处理。
再获得了我们自己的图片url后,我们需要将原有的html字符串中的图片替换为我们自己的url,然后删掉没用的html标签和样式,再粘贴到我们的编辑器中就可以了。
应用了这个方案后,再大部分情况下,用户可以直接ctrl + a,ctrl + c, ctrl + v,就将一篇完整的带图片的文章粘贴到我们的编辑器中了。
dealOutter = (text, html) => { // 站外处理
if (html.indexOf('<img ') === -1) { // 没有图片 走原来的算法
this.pasteText(text, html);
} else {
this.pasteSelection = document.getSelection().getRangeAt(0);
this.userCancelPaste = false;
const uploadId = String(window.Math.random()); // 上传id 保证多线程操作不会互相影响
this.uploadId = uploadId;
const imgs = html.match(/<img [^>]+>/g);
for (let i = 0; i < imgs.length; i += 1) {
// todo 容错 和 兼容不同网站
imgs[i] = imgs[i].match(/src="[^"]+"/)[0]
.replace('src="', '')
.replace('"', '')
.replace(/&/g, '&');
}
let html2 = html.replace(/<img [^>]+>/g, '@@@@BBT_IMG@@@@');
html2 = html2
.replace(/<\/p>/g, '\n')
.replace(/<\/div>/g, '\n')
.replace(/<br>/g, '\n')
.replace(/<[^>]+>/g, '')
.replace(/ /g, ' ');
this.parseImgUrls(imgs, html2, 0, uploadId);
}
}
parseImgUrls = (imgs2, html, index, uploadId) => {
if (this.isCanceled(uploadId)) {
return;
}
const imgs = imgs2;
const fd = new window.FormData();
this.showMsg(`<br/>您粘贴的内容中含有${imgs.length}张图片<br/>正在处理第${index + 1}张...`);
fd.append('url_list[]', [imgs[index]]);
window.fetch('/image/upload_by_urls', {
method: 'POST',
credentials: 'include',
body: fd,
})
.then(res => res.json())
.then((res) => {
if (res.status !== 'success' || res.data.length !== 1 || !res.data[0].photo_id) {
imgs[index] = { t: '100', url: errorImgSrc, alt: '图片解析失败.' };
} else {
imgs[index] = res.data[0];
}
this.parseImgUrl(imgs, html, index, uploadId);
})
.catch((e) => {
console.log(e);
imgs[index] = { t: '100', url: errorImgSrc, alt: '图片解析失败.' };
this.parseImgUrl(imgs, html, index, uploadId);
});
}
parseImgUrl = (imgs, html, index, uploadId) => {
if (this.isCanceled(uploadId)) {
return;
}
if (imgs.length - 1 === index) { // 最后一个
const texts = html.split('@@@@BBT_IMG@@@@');
document.getSelection().removeAllRanges();
document.getSelection().addRange(this.pasteSelection);
texts.map((text, i) => {
document.execCommand('insertText', false, text);
if (i < imgs.length) {
const json = {
t: imgs[i].t || '2',
id: imgs[i].photo_id,
path: imgs[i].url,
};
const imgHtml = `<img alt="${imgs[i].alt}" src="${imgs[i].url}" ${BBT_JSON}='${JSON.stringify(json)}' />`;
document.execCommand('insertHtml', false, imgHtml);
}
return null;
});
this.hideMsg();
} else {
this.parseImgUrls(imgs, html, index + 1, uploadId);
}
}