捣鼓TinyMCE粘贴图片并上传+Flask后台
好久没有编程了,最近需要完成一个小功能,为了方便,需要粘贴图片后上传到后台。前台编辑器用tinymce(N年前用过,我也就知道这个编辑器而已。这次使用下来感觉文档更丰富了),后台我用的Flask。昨天从下午4点开始一直捣鼓到半夜2点,终于完成了,这里大致记录一下遇到的问题和解决的办法。
1. 使用的tinymce版本是4.7.4,稍微熟悉了一下,advlist 插件不能用。 粘贴图片主要用的是自带的paste插件。
tinymce.init({
selector:'#mycontent',
menubar:false,
plugins: [
'code paste',
],
toolbar:'code',
height:400,
paste_data_images: true
});
2. 上面的代码已经能成功粘贴图片,并且显示在编辑框里面了。我查看了源代码,图片的src是这样的
<img src="blob:http://127.0.0.1:5000/e8b7743b-6637-45f5-8473-9cf5271cc841">
3. 我懵逼了,这是什么玩意儿,但是似乎听说过Blob这个东西。我又想了下我的思路,我是要把这个图像上传到后台,然后把后台的地址返回给客户端,然后把这个src给替换掉。 因此我的问题就是把这个图片读出来,然后上传。一开始我网上找到不少解决方法,可以把blob读出来,主要是用了HTML5的canvas 对象。用context 画图,然后输出DataURL,转化为Base64。 这一段耗费了我大量的时间。 下面的代码是有问题的,贴出来仅仅是为了表达完整的过程。
var Img = new Image();
Img.src=url;
width = Img.width; // 实际上是拿不到长宽的。
height = Img.height;
var canvas = document.createElement("canvas");
canvas.getContext("2d").drawImage(Img,0,0, width, height);
dataURL=canvas.toDataURL('image/jpeg');
大致的核心代码如上。rul: 就是上面 blob:http://.... 这一段。关键在于drawImage这个函数上,我为了看看这个画布上画出来的图像是否跟我粘贴的图像是一样的,因此在页面下部让这个画布显示出来,我遇到了几个问题
1. 第一次粘贴,画布无法显示图像,第二次粘贴后,画布会一次显示2个图像,而且错误 -__-!
2. 画布大小和图像大小不匹配。 打印了width和height 之后发现都是0。原来blob图像无法获得长宽。
3. 我粘贴的图像比较大,1800×3600以上,Base64太长了,传到后台,保存成图像之后,数据丢失,出来的是一片白色。
因此这条路基本上是走不通了。
4. 解决方法:换成纯二进制数据进行操作,不再转换。
直接看下面的代码吧,写的很粗,因为我不是很懂javascript。基本上全是复制粘贴过来的。
<script> globalcounter = 1; tinymce.init({
selector:'#mycontent',
menubar:false,
plugins: [
'code paste',
],
toolbar:'code',
height:400,
paste_data_images: true,
paste_preprocess: function(plugin, args) {
args.content = args.content.replace("<img", "<img id=\"pasted_image_" + parseInt(globalcounter) + "\"");
console.log(args.content)
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if (this.readyState == 4 && this.status == 200){ upload(this.response);
}
}; xhr.open('GET', args.content.split('"')[3]);
xhr.responseType = 'blob';
xhr.send(); function upload(BlobFile){
var x = new XMLHttpRequest();
x.onreadystatechange = function(){
if( this.readyState == 4 && this.status == 200 ){
data = this.responseText;
console.log('response data: ' + data);
id = parseInt(globalcounter++); // function setimg(id, data){
// if( document.getElementById("pasted_image_" + id) == null){
// setTimeout( setimg , 5000);
// }else{
// document.getElementById("pasted_image_" + id).setAttribute("src", data);
// }
// }
document.getElementById("mycontent_ifr").contentWindow.document.getElementById("pasted_image_" + id).setAttribute("src", data);
}
};
x.open('POST', '/pasteimg/');
x.send(BlobFile);
} } });
</script>
这里是后台的python代码,框架用的是Flask
@app.route('/pasteimg/', methods=['GET','POST'])
def paste_upload():
if request.method == 'POST':
imgdata = request.get_data()
file = open('test.png', 'wb')
file.write(imgdata)
file.close() imgsrc = "/static/img/60_1.png"
return Response( imgsrc, mimetype='application/text')
上面的代码有几个我遇到的问题,解决了。也有一些问题,我只是绕过了,但是没有真正解决;:
1. 用XMLHttpRequest 可以直接把img 读出来成为一段二进制数据 -- blob。而且没有大小限制,我贴的图片有时候size超过7位数。。也能够顺利上传到后台,相比之下,我觉得比Base64一串常常的字符串好多了。
2. tinymce 的paste_postprocess 中无法给插入对象设置id,这样我之后就没有办法获取图片了,因此,我只能在preprocess中设置了id,由于要插入多张图片,因此我用一个全局的计数器来递增id号。以后如果有多个textarea,那么还要再想办法。
3. jquery 的ajax方法不能传二进制,因此用XMLHttpRequest.
4. XMLHttpRequest 不能设置同步操作,设置了之后contenttype就不能设置blob,否则出错。我没时间去处理了,就用异步了。
5. 由于服务器端我命名规则还没有订好,因此我只是返回固定的一个图片,这样只要在前端能够顺利显示,说明整个路子都走通了。
6. 获取图片对象费了老大劲,原来tinymce自己是一个iframe,因此要先找到iframe,然后再找到里面的图片。 在chrome里面我直接用getElementById(”图片的id“)却始终找不到,奇怪。 后来我到Firefox中就能找到了。
7. 当服务器端把图像返回回来时,如果paste事件还没有完成,那么DOM对象还没有生成的话,图片对象是找不到的。虽然这种可能性很小,所以我设置了timeout,找不到就一直给我找,直到找到位置。当然也可以用一个wait 的gif,类似 博客园这么干。
8. 我的性子是不求甚解,能拼凑就拼凑,能猜就猜。。。。反正捣鼓出来就行了,什么代码优化之类的与我无缘。 只是我用了好多关键字搜索,但是搜出来的解决方案都有问题,所以我才写了这篇文章,希望也能帮助看文章的你节省宝贵的时间。
捣鼓TinyMCE粘贴图片并上传+Flask后台的更多相关文章
- 捣鼓TinyMCE 粘贴图片并上传+Django后台
前面一篇写了上传到Flask后台,但是我不熟悉Flask,原先想学习一下,据说是轻量级. 但是我发现,学习会浪费我大量的时间,因为我并不是以这个为生的,我的目标只是要完成功能,让我自己能尽早使用起来, ...
- ckeditor 实现ctrl+v粘贴图片并上传、word粘贴带图片
公司做的项目需要用到文本上传功能. Chrome+IE默认支持粘贴剪切板中的图片,但是我要粘贴的文章存在word里面,图片多达数十张,我总不能一张一张复制吧? 我希望打开文档doc直接复制粘贴到富文本 ...
- 如何在Chrome粘贴图片直接上传
背景 截图或页面复制图片,可以直接通过Ctrl+v 粘贴上传图片 原理 操作:复制(截图)=>粘贴=>上传 监听粘贴事件=>获取剪贴板里的内容=>发请求上传 浏览器:Chrom ...
- div中粘贴图片并上传服务器 div中拖拽图片文件并上传服务器
应用简介:此文主要是描述如何在前端div中直接ctrl+v 粘贴图片,并上传到服务器,包括拖拽图片文件到div中 应用场景描述:用QQ或者其它切图软件截图,在指定的div中ctrl+v 粘贴并显示,点 ...
- h5可预览 图片ajax上传 ,后台有点弱不知道数据怎么取,但是可以肯定数据上传成功了
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- xhEditor实现ctrl+v粘贴word图片并上传
自动导入Word图片,或者粘贴Word内容时自动上传所有的图片,并且最终保留Word样式,这应该是Web编辑器里面最基本的一个需求功能了.一般情况下我们将Word内容粘贴到Web编辑器(富文本编辑器) ...
- umeditor实现ctrl+v粘贴word图片并上传
图片的复制无非有两种方法,一种是图片直接上传到服务器,另外一种转换成二进制流的base64码目前限chrome浏览器使用首先以um-editor的二进制流保存为例:打开umeditor.js,找到UM ...
- ueditor实现ctrl+v粘贴word图片并上传
图片的复制无非有两种方法,一种是图片直接上传到服务器,另外一种转换成二进制流的base64码 目前限chrome浏览器使用,但是项目要求需要支持所有的浏览器,包括Windows和macOS系统.没有办 ...
- kindeditor实现ctrl+v粘贴word图片并上传
Chrome+IE默认支持粘贴剪切板中的图片,但是我要发布的文章存在word里面,图片多达数十张,我总不能一张一张复制吧?Chrome高版本提供了可以将单张图片转换在BASE64字符串的功能.但是无法 ...
随机推荐
- dubbo之配置规则
配置规则 向注册中心写入动态配置覆盖规则 1.该功能通常由监控中心或治理中心的页面完成. RegistryFactory registryFactory = ExtensionLoader.getEx ...
- CNN-CV识别简史2012-2017:从 AlexNet、ResNet 到 Mask RCNN
原文:计算机视觉识别简史:从 AlexNet.ResNet 到 Mask RCNN 总是找不到原文,标记一下. 一切从这里开始:现代物体识别随着ConvNets的发展而发展,这一切始于2 ...
- lamlmzhang的新博客开通了,欢迎大家的关注
从这里开始lamlmzhang的java开发之路~!
- ARM处理器的寄存器,ARM与Thumb状态,7中运行模式
** ARM处理器的寄存器,ARM与Thumb状态,7中运行模式 分类: 嵌入式 ARM处理器工作模式一共有 7 种 : USR 模式 正常用户模式,程序正常执行模式 FIQ模式(Fast ...
- Escaping Closures 两点:本质是生命周期标示符
1.block需要(拷贝)保存: 2.block引用的环境变量需要处理. 相当于oc中的copy block. Escaping Closures A closure is said to escap ...
- 一个数据去重sql
参考: https://www.jb51.net/article/129656.htm DELETE testcaseFROM testcase, ( SELECT max(id) id, a ...
- PHP 设计模式--基础
设计模式的宗旨就是:重用. 在面向对象中,类是用于生成对象的代码模版,而设计模式是用于解决共性问题的代码模版. 遵循这样的模板,我们可以设快速地设计出优秀的代码. 注意,设计模式只是模板,不是具体的代 ...
- Bootstrap练习:可折叠下拉菜单
代码: <!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="UT ...
- c# 用binary实现序列化和反序列化
直接用实例来说明序列化和反序列化: namespace DynamicTest{ class Program { static void Main(string[] args) { List<P ...
- [BZOJ 3221][Codechef FEB13] Obserbing the tree树上询问
[BZOJ 3221]Obserbing the tree树上询问 题目 小N最近在做关于树的题.今天她想了这样一道题,给定一棵N个节点的树,节点按1~N编号,一开始每个节点上的权值都是0,接下来有M ...