这是由tinymce-pastewordimage改变而来,原版只能在粘贴word的图片时图片文件本地化,现加入了复制网页内容时图片文件也本地化
tinymce-pastewordimage插件地址:hanghang2/tinymce-pastewordimage (github.com)
绕过防盗链参考网站:javascript - Referer和Referrer Policy及图片防盗链 - 个人文章 - SegmentFault 思否
注意:该插件需要配置好images_upload_handler属性
获取htmlContent时,不同的框架获取方式好像不一样,我这里用的是vue3,请各自测试获取方式
(function () {
const global = window.tinymce.util.Tools.resolve('tinymce.PluginManager');
const base64ToFile = (dataurl, filename = 'wps_office') => {
const arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1], bstr = atob(arr[1]);
let n = bstr.length;
const u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
return new File([u8arr], filename, {type: mime})
};
const hexToBase64 = hexString => {
return btoa(hexString.match(/\w{2}/g).map(char => {
return String.fromCharCode(parseInt(char, 16))
}).join(''))
};
function extractImageDataFromRtf(rtfData) {
if (!rtfData) {
return []
}
let regexPictureHeader = /{\\pict[\s\S]+?\\bliptag-?\d+(\\blipupi-?\d+)?({\\\*\\blipuid\s?[\da-fA-F]+)?[\s}]*?/;
let regexPicture = new RegExp(`(?:(${regexPictureHeader.source}))([\\da-fA-F\\s]+)\\}`, 'g');
let images = rtfData.match(regexPicture);
const result = [];
if (!images) {
regexPictureHeader = /{\\pict[\s\S]+?(\\pngblip-?\d+)?(\\wmetafile8-?\d+)?{\\\*\\blipuid\s?[\da-fA-F]+[\s}]*?/;
regexPicture = new RegExp(`(?:(${regexPictureHeader.source}))([\\da-fA-F\\s]+)\\}`, 'g');
images = rtfData.match(regexPicture)
}
if (images) {
for (const image of images) {
let imageType = false;
if (image.includes('\\pngblip')) {
imageType = 'image/png'
} else if (image.includes('\\jpegblip')) {
imageType = 'image/jpeg'
}
if (imageType) {
const hex = image.replace(regexPictureHeader, '').replace(/[^\da-fA-F]/g, '');
const base64 = `data:${imageType};base64,${hexToBase64(hex)}`;
result.push({base64, file: base64ToFile(base64)})
}
}
}
return result
}
function getBase64Image(img, callback) {
const image = new Image();
image.crossOrigin = 'anonymous'; // 跨域
image.referrerPolicy = 'no-referrer'; //绕过防盗链
image.onload = () => {
const canvas = document.createElement('canvas');
canvas.useCORS = true;
const ctx = canvas.getContext('2d');
canvas.height = image.naturalHeight;
canvas.width = image.naturalWidth;
ctx.drawImage(image, 0, 0);
const dataUrl = canvas.toDataURL();
callback && callback(dataUrl)
}
image.onerror = (error) => {
console.log(error)
callback && callback()
}
image.src = img.src;
}
const getHtmlImgFiles = (e, editor) => {
let htmlContent = e.clipboardData.getData('text/html');
if (htmlContent) {
let element = document.createElement('div');
element.innerHTML = htmlContent;
const imgElements = element.querySelectorAll('img');
if (imgElements && imgElements.length > 0) {
for (let i = 0; i < imgElements.length; i++) {
let imgEl = imgElements[i];
if (imgEl.src.startsWith('http') || imgEl.src.startsWith('ftp')) {
getBase64Image(imgEl, (base64) => {
if (base64) {
imgEl.setAttribute("src", base64);
}
if (i === imgElements.length - 1) {
editor.insertContent(element.innerHTML)
}
})
} else {
if (i === imgElements.length - 1) {
editor.insertContent(element.innerHTML)
}
}
}
e.preventDefault();
}
}
}
const getImgFiles = (e) => {
if (e.clipboardData || e.originalEvent) {
var clipboardData = (e.clipboardData || e.originalEvent.clipboardData);
if (clipboardData.items) {
var items = clipboardData.items, len = items.length;
for (var i = 0; i < len; i++) {
if (items[i].type.indexOf('text/rtf') !== -1) {
return extractImageDataFromRtf(clipboardData.getData('text/rtf'))
}
}
}
}
};
const Plugin = () => {
global.add('pasteuploadimage', editor => {
let imgs = [], index = 0;
editor.on('paste', (e) => {
imgs = [];
index = 0;
const blobInfo = getImgFiles(e);
if (blobInfo && blobInfo.length) {
imgs = blobInfo
}
// 复制网页内容,图片本地化
getHtmlImgFiles(e, editor)
});
editor.on('init', () => {
editor.parser.addNodeFilter('img', (nodes) => {
if (!nodes.some(node => node.attr('src').indexOf('file://') === 0)) {
return
}
for (let i = 0, l = nodes.length; i < l; i++) {
const node = nodes[i];
if (node.attr('src').indexOf('file://') === 0) {
if (imgs[index]?.base64) {
node.attr('src', imgs[index]?.base64);
index++
} else {
node.remove()
}
}
if (i + 1 === nodes.length) {
imgs = [];
index = 0
}
}
})
})
})
};
Plugin()
})();
引用插件
// 添加扩展插件
external_plugins: {
pasteuploadimage: '/tinymce/plugins/pasteuploadimage/plugin.min.js',
},
网友评论