tinymce基本的图片上传和文本已经很多人写过了,这里放一个中文文档
TinyMCE中文文档中文手册http://tinymce.ax-z.cn/ 项目中遇到需求能够让粘贴进来的图片上传到我们自己的服务器上,而不是单纯的引用一个连接,还有一个问题是同时粘贴进来的图文生成的图片标签是没有宽度和高度的,以下是解决方案。
单纯需要单图片复制自动上传的话只需要加一个配置
配置在tynemce.init({})里
paste_data_images: true,//单独粘贴的图片会执行上传图片的操作
同时记得在plugin中加上paste
以下有两种粘贴内容的来源,一种是从word中复制图文一种是从网页中复制图文
同时我们需要另外一个插件叫powerpaste
PowerPaste plugin | Docs | TinyMCE 官方的插件文档,使用百度翻译可轻松食用
贴一个插件下载的地址
链接:https://pan.baidu.com/s/1bJblEF53oBBvBKdYgnC68A
提取码:6666
支持最新的tinymce5
一、从word中复制图文粘贴进富文本
我只粘贴关键的配置,具体配置相关内容请参考文档
要注意的是从word中图文一起复制后blobInfo.blob()返回的就不是File实例而是Blob实例,我这里用的是原型判断,因为后端的上传接口接受的是File所以将blob转换为File
{
powerpaste_allow_local_images:true,
powerpaste_word_import: 'clean',
images_upload_handler: function(blobInfo, succFun, failFun) {
var xhr, formData
// var file =new File([blobInfo. blob(),])
var file = blobInfo.blob()// 转化为易于理解的file对象
//如果file是blob实例那么必须转换为file
if(Object.getPrototypeOf(file).isPrototypeOf(new Blob)){
//文件名随便设置,服务器会重新存储名称,要有后缀
file=new window.File([file], 'test.png', {type: file.type})
}
xhr = new XMLHttpRequest()
xhr.withCredentials = false
xhr.open('POST', uploadUrl)//此处的uploadUrl是文件上传的接口路径
xhr.setRequestHeader('token', token)
xhr.onload = function() {
console.log(xhr);
var json
if (xhr.status != 200) {
failFun('HTTP Error: ' + xhr.status)
return
}
json = JSON.parse(xhr.responseText)
if (!json || typeof json.url != 'string') {
failFun('Invalid JSON: ' + xhr.responseText)
return
}
succFun(json.url)
}
formData = new FormData()
formData.append('file', file, file.name)// 此处与源文档不一样
xhr.send(formData)
}
}
word中复制的图文,图片会自动生成大小,但是单独复制的图片没有,后面再处理
边写代码变看文档,貌似是没有html图文上传自动上传图片到服务器的配置,但是有粘贴回调
查阅了半天,老是想着用回调自己给我解决反而浪费了不少时间,下面介绍一下所有复制粘贴的图片生成的img没有宽高的解决方法,这边感谢一下这位作者的思路https://blog.csdn.net/weixin_41442779/article/details/108800954
一、配置粘贴回调事件
由于tinymce的这些回调都是不支持异步的,所以任何使用异步的手段修改args.content方法都是无效的,所以我们选择直接修改tinymce内容绑定的value
paste_preprocess:function (plugin, args) {
id=Date.parse(new Date());//作用是给所有的img一个不会重复的id
sizeArr=[];//存储所有图片的尺寸信息,格式:[{id:123,width:234,height:123}]
let lastIndex=0;//存储args.content查询的下标
flag=false;//判断有没有图片
//此处给所有img加上id
for(let i=0;args.content.indexOf('<img',lastIndex)!=-1;i++){
flag=true
args.content=args.content.replace('<img',`<img id=${id+i}`)
i++;
lastIndex=args.content.indexOf('<img',lastIndex)+1
}
如果存在图片就执行获取图片尺寸的方法
if(flag){
that.getImageSize(args.content)
}
},
二、getImageSize方法
getImageSize(str) {
//此处str为args.content,以下通过正则获取img标签的src属性
let urlArr=str.match(/src=[\'\"]?([^\'\"]*)[\'\"]?/gi)
let promiseArr=[]
//此处将src=删除
urlArr=urlArr.map(item=>{
return item.slice(5,-1)
})
//此处为promiseArr添加img的异步onload事件
for(let i=0;i<urlArr.length;i++){
let img=new Image()
img.src=urlArr[i]
promiseArr.push(new Promise(resolve=>{
//如果不是用onload 立马获取的宽高为空
//如果想提高效率可以设置定时器,定时获取宽高,比等待onload要快很多
img.onload=function(){
sizeArr.push({width:img.width,height:img.height,id:id+i})
resolve()
}
}))
}
//当所有图片都加载好之后把id replace为宽高就大功告成了
Promise.all(promiseArr).then(()=>{
sizeArr.forEach(item=>{
// console.log(this.value.indexOf(`id="${item.id}"`));
this.value=this.value.replace(`id="${item.id}"`,`height=${item.height} width=${item.width}`)
})
})
},
三、自动上传到自己的服务器
通过配置白名单然后在回调函数与getimagesize方法中过滤掉已经在自己服务器上的图片同样通过promise可以很轻松的完成上传,再根据id替换url就很简单了,由于添加powerpaste插件后再配置一下word粘贴的图文和单独的图片都会自动上传,具体网页url上传就不赘述,如上的方法就可以实现。
四、一点坑
老想着用回调走了很多弯路,切记,tinymce回调不支持异步 一开始看粘贴回调和url过滤回调不同不是用return 而是args.content=的形式赋值抱了不必要的期望,把字符串解析为标签树,然后用promise给标签树加上宽高再转回字符串,发现这种赋值根本不生效.....
然后想着把args,content和总的value比对进行replace,竟然!!!!!!!!!!!!!!!