欢迎各位兄弟 发布技术文章
这里的技术是共享的
1) 本地一个apache服务器, my.qyweixin.com,路径指向企业微信的图像的路径, C:\Users\16666739\Documents\WXWork
2) sites\all\libraries\ueditor\ueditor.all.js 里面
me.addListener('beforepaste', function (cmd, html) {
这个函数里面的最后 约 20452行,加上两行代码
html.html = html.html.replaceAll('file:///C:/Users/16666739/Documents/WXWork','http://my.qyweixin.com:82'); //替换为apache服务器的网站路径
html.html = html.html.replaceAll('<img','<br style="height:1px" /><img style="max-width:520px;" '); //把图像设为最宽520px
3) 使用 get_images模块,见 /node-admin/1134
此时 就可以复制企业微信的图文了,剪切的含图片的内容就可以直接转变成服务器上的图了,哎,真搞不懂!
ueditor.all-for-word-and-wps-img-paste-ok---from-imgurl-ok---drag-img-ok.js.txt #包括wps 自然在aaaa上用的是它
ueditor.all-for-word-img-paste-ok---from-imgurl-ok---drag-img-ok.js.txt #除了wps
上面两个文件的区别仅仅在 约 7543 行
即把 const regexPictureHeader = /{\\pict[\s\S]+?\\bliptag-?\d+(\\blipupi-?\d+)?({\\\*\\blipuid\s?[\da-fA-F]+)?[\s}]*?/;
改成了 const regexPictureHeader = /{\\pict[\s\S]+?({\\\*\\blipuid\s?[\da-fA-F]+)[\s}]*/;
UE编辑器本身就集成了WORD图文粘贴,可惜由于年代久远,官方放弃了维护且现代浏览器不在需要毒瘤flash了,所以UE编辑器就用不了word图文粘贴。
浏览器技术也在不断改进,要解决word图文粘贴有几种做法:
浏览器控件(扩展)。
让用户的浏览器安装控件,直接读取word保存在硬盘的临时图片。但是这个体验不够好。
先将word文件上传到服务器后端,后端解析word文件后,再回调到前端编辑器。
比较常见的实现方法,但是对于纯前端来说,我觉得这种做法通用性低,仅适用公司自用。
纯前端解决。本次实现的方式。
首先UE本身已经实现WORD的图文粘贴,只是图片转换没有做解决方案,会用一张临时图片顶替。因此本次任务就是去解决前人遗留的问题。
众所周知,复制整份图文word文档,在浏览器中粘贴,你通过监听剪切板内容,会发现图片标签都是以 file:///
开头的。 由于浏览器安全机制,他会阻止你加载本地资源。所以摆在我眼前的问题就成了:如何将file:///
开头的图片,转换为base64。 找到了目标后,就很好办了。
尽管找到了目标,但是要将本地图片转换为base64不是一个容易的事情。不过这些小困难想难倒一个拥有10多年面向搜索引擎开发经验的程序员来说,只是一个易事。
皇天不负有心人,我想到了用过JS FileReader来转换base64 。思路:
读取剪切板所有本地图片地址。
手动追加 <input type="file">
并将本地图片地址进行手动模拟。
我就把时间花在如何将图片地址添加到input file中,且是模式用户的。 几小时过去,我认为这个思路是错误的。
正当我一筹莫展的时候,我想起了知名的富文本编辑器——CK5。CK5已经实现了word图文粘贴,遂到官网一试,看看源码,CK5成功将图片转换为base64了。果断下载CK5源码到本地一探究竟。
在CK5源码的packages库中,可以找到一个名为ckeditor5-paste-from-office
目录。大概看了一下里面的源码,然而我也看不懂。
再后来,我忘记我搜索什么关键词了依次在掘金找到juejin.cn/post/701372… , /node-admin/17946 通过CK5和RTF关键词,找到一篇别人写的文章:blog.csdn.net/Jioho_chen/… /node-admin/19460
通过站在巨人之上,整个解决方案就出来了。
由于篇幅和时间限制,如何整合到UE的思路我就不叙述了,直接来实现的方案:打开UE的核心文件ueditor.all.js
首先,在核心文件开头附近,声明一个数组,用于存放转换好的图片。大概30行附近左右,添加
var wordImg = [];
复制代码
找到_initEvents: function () {
,大概7454行,这里大概就是UE初始化的代码,在这里可以监听到当前UE编辑器的DOM。 接下来将整个_initEvents覆盖如下代码即可,如果你有对比器,可以根据我这部分获取差异。
/**
* 初始化UE事件及部分事件代理
* @method _initEvents
* @private
*/
_initEvents: function () {
var me = this,
doc = me.document,
win = me.window;
//监听word复制粘贴功能
doc.addEventListener("paste", function (e) {
if (!(e.clipboardData && e.clipboardData.items)) {
return;
}
const clipboardData = e.clipboardData;
//粘贴板中的HTML文本
let copyStr = clipboardData.getData('text/html');
//粘贴板中的RTF数据
let rtf = clipboardData.getData('text/rtf');
//获取粘贴板中图片的数量
let imgs = me.findAllImageElementsWithLocalSource(copyStr);
me.replaceImagesFileSourceWithInlineRepresentation(imgs, me.extractImageDataFromRtf(rtf))
})
me._proxyDomEvent = utils.bind(me._proxyDomEvent, me);
domUtils.on(doc, ['click', 'contextmenu', 'mousedown', 'keydown', 'keyup', 'keypress', 'mouseup', 'mouseover', 'mouseout', 'selectstart'], me._proxyDomEvent);
domUtils.on(win, ['focus', 'blur'], me._proxyDomEvent);
domUtils.on(me.body,'drop',function(e){
//阻止ff下默认的弹出新页面打开图片
if(browser.gecko && e.stopPropagation) { e.stopPropagation(); }
me.fireEvent('contentchange')
});
domUtils.on(doc, ['mouseup', 'keydown'], function (evt) {
//特殊键不触发selectionchange
if (evt.type == 'keydown' && (evt.ctrlKey || evt.metaKey || evt.shiftKey || evt.altKey)) {
return;
}
if (evt.button == 2)return;
me._selectionChange(250, evt);
});
},
复制代码
接着在后面添加如下代码
//获取粘贴板中图片数量
findAllImageElementsWithLocalSource:function(copyStr){
let imgs = $(copyStr).find('img');
return imgs;
},
//处理图片信息
extractImageDataFromRtf:function(rtfData){
if (!rtfData) {
return [];
}
const regexPictureHeader = /{\pict[\s\S]+?\bliptag-?\d+(\blipupi-?\d+)?({\*\blipuid\s?[\da-fA-F]+)?[\s}]*?/;
const regexPicture = new RegExp('(?:(' + regexPictureHeader.source + '))([\da-fA-F\s]+)\}', 'g');
const images = rtfData.match(regexPicture);
const result = [];
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) {
result.push({
hex: image.replace(regexPictureHeader, '').replace(/[^\da-fA-F]/g, ''),
type: imageType
});
}
}
}
return result;
},
//16进制转换为base64
_convertHexToBase64:function(hexString){
return btoa(hexString.match(/\w{2}/g).map(char => {
return String.fromCharCode(parseInt(char, 16));
}).join(''));
},
//存储图片资源
replaceImagesFileSourceWithInlineRepresentation:function(imageElements, imagesHexSources){
// Assume there is an equal amount of image elements and images HEX sources so they can be matched accordingly based on existing order.
if (imageElements.length === imagesHexSources.length) {
for (let i = 0; i < imageElements.length; i++) {
const newSrc = `data:${imagesHexSources[i].type};base64,${this._convertHexToBase64(imagesHexSources[i].hex)}`;
wordImg.push(newSrc);
// writer.setAttribute('src', newSrc, imageElements[i]);
}
}
console.dir(wordImg)
},
复制代码
上述代码作用是监控粘贴板,并将转换好的图片保存在wordImg数组中。
接下来在文件搜索//todo base64暂时去掉,后边做远程图片上传后,干掉这个
将下方的代码去除。最终样子大概如下:
case 'img':
//todo base64暂时去掉,后边做远程图片上传后,干掉这个
if (val = node.getAttr('src')) {
}
node.setAttr('_src', node.getAttr('src'));
break;
复制代码
最后,定位到 UE.plugin.register('wordimage',function(){
大概13990行。直接将inputRule : function (root) {
覆盖替换如下代码
inputRule : function (root) {
utils.each(root.getNodesByTagName('img'), function (img, key) {
var attrs = img.attrs,
flag = parseInt(attrs.width) < 128 || parseInt(attrs.height) < 43,
opt = me.options,
src = opt.UEDITOR_HOME_URL + 'themes/default/images/spacer.gif';
if (attrs['src'] && /^(?:(file:\/+))/.test(attrs['src'])) {
img.setAttr({
width:attrs.width,
height:attrs.height,
alt:attrs.alt,
src:wordImg[key],
'style':'background:url(' + ( flag ? opt.themePath + opt.theme + '/images/word.gif' : opt.langPath + opt.lang + '/images/localimage.png') + ') no-repeat center center;border:1px solid #ddd'
})
}
})
//清空调用记录
wordImg = [];
}
复制代码
至此,整个UE编辑器可以支持word图文粘贴了。需要注意的是:本次修改没有将图片上传到后端服务器。具体的逻辑请大家自行修改了。x
效果图:
对了,RTF目前还是实验性功能,可能随着浏览器的升级,这次修改又双叒叕失效。
考虑到上面代码有些分散,可以直接查看我的GITEE 本次代码的提交:gitee.com/fallBirds/P…
打个小广告,如果大家对文档编辑有需求,可以使用我编写的文档管理:PESCMS DOC gitee.com/fallBirds/P…
作者:天机星
链接:https://juejin.cn/post/7096322277641289735
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
来自 https://juejin.cn/post/7096322277641289735