欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

ueditor实现ctrl+v粘贴word图片并上传 有大用

图片的复制无非有两种方法,一种是图片直接上传到服务器,另外一种转换成二进制流的base64码

目前限chrome浏览器使用,但是项目要求需要支持所有的浏览器,包括Windows和macOS系统。没有办法在网上搜了很多资料终于找到一个产品:WordPaster。

浏览器方面能够支持ie6,ie7,ie8,ie9,ie10,chrome,firefox,edge几乎所有的浏览器。

编辑器基本上也是全部都支持,并且支持vue,整合也比较简单。

首先以um-editor的二进制流保存为例:

打开umeditor.js,找到UM.plugins['autoupload'],然后找到autoUploadHandler方法,注释掉其中的代码。

加入下面的代码:

//判断剪贴板的内容是否包含文本

//首先解释一下为什么要判断文本是不是为空

//在ctrl+c word中的文字或者图片之后会返回1种(image/png)或者4种type(text/plain,text/html,text/rtf,image/png)类型的对象

//为了兼容4种格式的情况,做了如下的判断

//如下代码:e.originalEvent.clipboardData.items获得剪贴板的内容

//当粘贴了文本之后text是不为空的,同时也会返回当前文本的图片类型

//如果有文字的话不做任何的处理,如果只粘贴图片的话文本一定是空的,包括复制的桌面图片或者截图的图片

var text = e.originalEvent.clipboardData.getData("text");

if(text == ""){

var items=e.originalEvent.clipboardData.items;

for (var i = 0, len = items.length; i < len; i++) {

var item = items[i];

if ( item.kind == 'file' && item.type.indexOf('image/') !== -1 ) {

var blob = item.getAsFile();

getBase64(blob, function( base64 ) {

//sendAndInsertImage(base64,me); 上传到服务器

setBase64Image(base64,me);

});

//阻止默认事件, 避免重复添加;

e.originalEvent.preventDefault();

};

}

}

两个方法:

//执行插入图片的操作

function setBase64Image(base64, editor) {

editor.execCommand('insertimage', {

src: base64,

_src: base64

});

}

//获得base64

function getBase64(blob, callback) {

var a = new FileReader();

a.onload = function(e) {

callback(e.target.result);

};

a.readAsDataURL(blob);

};

wordpaster与umeditor的整合教程

1.添加按钮样式

样式代码

.edui-icon-wordpaster{width: 16px;height: 16px;background: url('../../../../wordpaster/css/paster.png') no-repeat !important;}

2.在工具栏中添加按钮

3.复制wordpaster目录到项目中

4.在页面中注册按钮

在页面中添加引用

<linkhref="umeditor/themes/default/css/umeditor.min.css" type="text/css" rel="stylesheet">

<scripttype="text/javascript" src="umeditor/third-party/jquery.min.js" charset="utf-8"></script>

来自   https://www.bbsmax.com/A/kPzO4VYoJx/




允许ueeditor编辑器直接粘贴word文本


前言

UE编辑器本身是集成WORD图贴的,可惜由于历史悠久,官方已经放弃维护,现代浏览器也不再需要癌闪了,所以UE编辑器不支持word图贴。

浏览器技术也在不断完善,解决word贴图文字的方法有以下几种:

  1. 浏览器控件(展开)。

让用户的浏览器安装控件,直接读取保存在硬盘上的word 临时图片。但是体验还不够好。

  1. 先将word文件上传到服务器后端,后端解析word文件后,再回调到前端编辑器。

比较常见的实现方式,但是对于纯前端来说,我觉得这种方式通用性较低,仅供公司自用。

  1. 纯前端解决方案。这种实现方式。

解决方案

首先UE本身已经实现了WORD粘贴图片和文字,只是没有图片转换的解决方案,将替换...用临时图片。所以,这个任务就是解决前人留下的问题。

众所周知,复制整个图片和文字word文件,粘贴……在浏览器中,你听听剪贴板的内容,你会发现图片标签都标有file:///开头。由于浏览器的安全机制,它会阻止你加载本地资源。于是摆在我面前的问题就变成了:如何整合file:///第一张图片,转换成base64。找到目标之后,就很容易做到了。

错误的思维方式

尽管找到了目标,但是要将本地图片转换为base64并不是一件容易的事情。但是这些小困难要让一个拥有10多年搜索引擎开发经验的程序员为难,简直是轻而易举的事情。

天子乐于助人,想到了用JS FileReader 来转换base64。思路:

  1. 读取剪贴板的所有本地图片地址。

  2. 手动添加<input type="file">和手动模拟本地图片地址。

我只是花时间在如何将图片地址添加到输入文件中,并且它是针对模式用户的。几个小时后,我觉得这个想法是错误的。

站在巨人上解决问题

不知所措的时候想到了大名鼎鼎的富文本编辑器——CK5.CK5 已经完成了word的图形粘贴,于是就去官网试了一下,看源码,CK5成功将图片转成base64了. 果断下载CK5 去本地源码一探究竟。

在 CK5 源代码包的库中,可以找到一个叫做ckeditor5-paste-from-officeCatalog 的。大概看了里面的源码,不过,看不懂。

后来忘记搜索了哪些关键词,依次在掘金中找到了juejin.cn/post/701372…,采用CK5和RTF关键词,找了一篇别人写的文章:blog.csdn.net/Jioho_chen/…

通过站在巨人上,整个解决方案就出来了。

实施方案

由于篇幅和时间的限制,如何集成到UE中的思路我就不赘述了,直接实现的一个方案:打开UE的核心文档ueditor.all.js

首先,在core文件的开头附近,声明一个数组,用来存放转换后的图片。大概 30 左右,加到

var wordImg = [];
 Copy code 

找到_initEvents: function () {,大概是 7454 就可以了,这大概是 UE 初始化的代码,这里可以监控当前 UE 编辑器的 DOM。接下来整个 _initEvents 改写下面的代码就行了,如果有比较器的话,可以根据我的部分来获取差异。

/** * initialization UE Events and some event agents * @method _initEvents * @private */
_initEvents: function () {
var me = this,
doc = me.document,
win = me.window;
// monitor word Copy and paste function 
doc.addEventListener("paste", function (e) {
if (!(e.clipboardData && e.clipboardData.items)) {
return;
}
const clipboardData = e.clipboardData;
// Paste the... In the board HTML Text 
let copyStr = clipboardData.getData('text/html');
// Paste the... In the board RTF data 
let rtf = clipboardData.getData('text/rtf');
// Get the number of pictures in the pasteboard 
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){
// prevent ff The default pop-up page opens the picture 
if(browser.gecko && e.stopPropagation) { e.stopPropagation(); }
me.fireEvent('contentchange')
});
domUtils.on(doc, ['mouseup', 'keydown'], function (evt) {
// Special keys do not trigger selectionchange
if (evt.type == 'keydown' && (evt.ctrlKey || evt.metaKey || evt.shiftKey || evt.altKey)) {
return;
}
if (evt.button == 2)return;
me._selectionChange(250, evt);
});
},
 Copy code 

然后添加以下代码

// Get the number of pictures in the pasteboard
findAllImageElementsWithLocalSource:function(copyStr){
let imgs = $(copyStr).find('img');
return imgs;
},
// Process picture information
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 Base to zero base64
_convertHexToBase64:function(hexString){
return btoa(hexString.match(/\w{2}/g).map(char => {
return String.fromCharCode(parseInt(char, 16));
}).join(''));
},
// Store picture resources
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)
},
 Copy code 

以上代码用于监控粘贴板,并将转换后的图片保存在 wordImg Array 中。

接下来,搜索文件//todo base64 Remove... For the time being , After remote image upload , Get rid of this 删除下面的代码。最终外观如下:

 case 'img':
//todo base64 Remove... For the time being , After remote image upload , Get rid of this 
if (val = node.getAttr('src')) {
}
node.setAttr('_src', node.getAttr('src'));
break;
 Copy code 

最后,找到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'
})
}
})
// Clear the call record 
wordImg = [];
}
 Copy code 

这样,整个UE编辑器就可以支持word的图文粘贴了。需要注意的是:本次修改并没有将图片上传到后端服务器。具体逻辑请自行修改.x

设计草图:

登录.gif

顺便说一句,RTF目前还是一个实验性功能,可能随着浏览器的升级,这个版本又一次失效了。

集成代码

考虑到上面代码有点零散,可以查看我的GITEE这个代码提交:gitee.com/fallBirds/P...

做一个小广告,如果你有文档编辑的需求,可以使用我写的文档管理:PESCMS DOC gitee.com/fallBirds/P...


来自  https://qdmana.com/2022/131/202205112014481096.html


普通分类: