UEditor插件开发,基于Base64编码上传图片
引用下UEditor官网的介绍,阐述下Ueditor是什么。官网地址http://ueditor.baidu.com/website/。
UEditor是由百度web前端研发部开发所见即所得富文本web编辑器,具有轻量,可定制,注重用户体验等特点,开源基于MIT协议,允许自由使用和修改代码...
开发背景:本程序提供给站长老婆写各种游记,及各种小清新文章。但是老婆大人总抱怨上传图片不好用,每次都要先调整小于网站限制大小后才能够上传。于是乎开发需求就是这么产生了。本来是打算用ActiveX插件来解决这个问题,但是后来发现这个方案对浏览器支持并不是特别完成。所以使用html5的Canvas来解决这个问题,现在本地使用Canvas调整上传图片的长宽,然后转换成base64使用post发送到服务器。
网站后台使用的是UEditor编辑器,框架使用了ThinkPHP,所以一并使用了专门为ThinkPHP编写的UeditorController.class.php。开源社区网址:https://github.com/Nintendov/Ueditor-thinkphp
在Ueditor提供的例子下创建一个ueditor插件。官网文档说明:http://fex.baidu.com/ueditor/#dev-developer
在\ueditor\third-party下创建一个文件夹,取名为uploadImage
根据网站提供的例子,将addCustomizeDialog.js复制到文件夹下面并作如下编辑
addCustomizeDialog.js
UE.registerUI('dialog', function(editor, uiName) { //获取当前js文件的绝对路径 var js = document.scripts; var jsPath; for (var i = js.length; i > 0; i--) { if (js[i - 1].src.indexOf("addCustomizeDialog.js") > -1) { jsPath = js[i - 1].src.substring(0, js[i - 1].src.lastIndexOf("/") + 1); } } //alert(jsPath); //创建dialog var dialog = new UE.ui.Dialog({ //指定弹出层中页面的路径,这里只能支持页面,因为跟addCustomizeDialog.js相同目录,所以无需加路径 iframeUrl: jsPath+'uploadPreview.html?url='+editor.ui.serverUrl, //需要指定当前的编辑器实例 editor: editor, //指定dialog的名字 name: uiName, //dialog的标题 title: '上传图片', //指定dialog的外围样式 cssRules: "width:1024px;height:520px;", //如果给出了buttons就代表dialog有确定和取消 buttons: [{ className: 'edui-okbutton', label: '确定', onclick: function() { var jsonData=$('#'+dialog.id+'_iframe').contents().find('#jsonData').html(); if(jsonData!='') { editor.focus(); //jsonData.substr(1,jsonData.length-1); //jsonData="{\"rltData\":"+jsonData+"}"; jsonData=jQuery.parseJSON(jsonData); $.each(jsonData, function(index, val) { editor.execCommand('insertHtml','<p><img src="'+val.url+'" width=550 /></p>'); }); dialog.close(true);} else { alert('请上传文件后点击【确定】'); } } }, { className: 'edui-cancelbutton', label: '取消', onclick: function() { dialog.close(false); } }] }); //参考addCustomizeButton.js var btn = new UE.ui.Button({ name: 'dialogbutton' + uiName, title: 'dialogbutton' + uiName, //需要添加的额外样式,指定icon图标,这里默认使用一个重复的icon cssRules: 'background-position: -580px 0;', onclick: function() { dialog.render(); dialog.open(); } }); return btn; } /*index 指定添加到工具栏上的那个位置,默认时追加到最后,editorId 指定这个UI是那个编辑器实例上的,默认是页面上所有的编辑器都会添加这个按钮*/ );
由于Ueditor的对话框插件是通过iframe实现的,所以还需要创建一个网页。取名为uploadPreview.html,引用css文件为fileinput.css,是一个Jquery的第三方插件的UI。实现逻辑不再赘述,直接帖代码。
uploadPreview.html
<html> <head> <meta charset='utf-8'> <script type="text/javascript" src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script> <link rel="stylesheet" type="text/css" href="fileinput.css"> <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet"> <style type="text/css"> body { height: 440px; overflow: hidden; } form { margin-left: 15px; } .browse-btn { position: relative; display: inline-block; background: #D0EEFF; border: 1px solid #99D3F5; border-radius: 4px; padding: 4px 12px; overflow: hidden; color: #1E88C7; text-decoration: none; text-indent: 0; line-height: 20px; cursor: pointer; } .browse-btn:hover { background: #AADFFD; border-color: #78C3F3; color: #004974; text-decoration: none; cursor: pointer; } #upload-Img { width: 144px; height: 41px; cursor: pointer; font-size: 30px; outline: medium none; position: absolute; filter: alpha(opacity=0); -moz-opacity: 0; opacity: 0; left: 0px; top: 0px; } #uploadEach { float: left; } form { width: 100%; } </style> </head> <body> <div class='file-preview-thumbnails file-drop-zone'> </div> <form> <a href="#" class="browse-btn">+添加文件 <input id='upload-Img' type="file" name="photo" onchange="readFiles(event)" /> </a> <a href="#" id="upload-each" class="browse-btn">上传所有文件</a> </form> <div id='jsonData' style="display:none"></div> <script type="text/javascript"> var resultJson = []; var serverUrl = window.location.href.split('=')[1]; if (serverUrl == null) { console.error('serverUrl为空!'); } serverUrl = serverUrl + '?action=uploadimagebase64'; $('#upload-each').click(function(event) { var l = $('.file-preview-thumbnails').find('img').length; if (l == 0) { alert('请选择要添加的文件!'); } else { $('.file-preview-thumbnails').find('img').each(function(index, el) { uploadOneImg($(this).attr('randid')); }); } }); function uploadOneImg(randId) { urlData = $('#preview-' + randId).find('img').attr('src'); $.ajax({ //contentType: 'application/json; charset=utf-8', type: 'post', url: serverUrl, data: { upfile: urlData }, datatype: 'json', success: function(data) { var obj = eval('(' + data + ')'); if (obj.state == 'SUCCESS') { var icon = $('#preview-' + randId).find('.file-upload-indicator'); if (resultJson.length == 0) { resultJson = jQuery.parseJSON('[' + data + ']'); } else { resultJson.push(jQuery.parseJSON(data)); } $('#jsonData').html(JSON.stringify(resultJson)); //icon.attr('title', '上传成功'); //icon.removeClass('glyphicon-hand-down'); //icon.removeClass('glyphicon-hand-down'); //icon.addClass('glyphicon glyphicon-ok-sign text-success'); icon.find('i').removeClass(); icon.find('i').addClass('glyphicon glyphicon-ok-sign text-success'); $('#preview-' + randId).find('.file-footer-buttons').find('.kv-file-upload').remove(); $('.file-thumb-progress').removeClass('hide'); $('.progress-bar').html('100%'); $('.progress-bar').css('width', '100%'); } else { var icon = $('#preview-' + randId).find('.file-upload-indicator'); icon.find('i').removeClass(); icon.find('i').addClass('glyphicon glyphicon-alert text-warning'); console.error(obj.state); } //alert('成功!'); }, error: (function() { alert('上传失败'); }) }); } function _getRandomString(len) { len = len || 32; var $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678'; // 默认去掉了容易混淆的字符oOLl,9gq,Vv,Uu,I1 var maxPos = $chars.length; var pwd = ''; var i; for (i = 0; i < len; i++) { pwd += $chars.charAt(Math.floor(Math.random() * maxPos)); } return pwd; } function createPreviewEl(randId, i, base64, title) { var innerHTML = '<div class="file-actions"><div class = "file-footer-buttons"><button type = "button" randid="' + randId + '" class = "kv-file-upload btn btn-xs btn-default" title="上传文件"> <i class = "glyphicon glyphicon-upload text-info"> </i> </button> <button type = "button" randid="' + randId + '" class = "kv-file-remove btn btn-xs btn-default"title = "删除文件"> <i class = "glyphicon glyphicon-trash text-danger"> </i></button></div> <div class = "file-upload-indicator" title = "没有上传"> <i class = "glyphicon glyphicon-hand-down text-warning"> </i></div><div class = "clearfix" > </div></div>'; var el = $('<div/>'); el.addClass('file-preview-frame'); el.attr('id', 'preview-' + randId); el.attr('data-fileindex', i); var elImage = $('<img/>'); elImage.attr('src', base64); elImage.css('height', '90px'); elImage.addClass('file-preview-image'); elImage.attr('title', title); elImage.attr('alt', title); elImage.attr('randid', randId); var elFooter = $('<div/>'); elFooter.addClass('file-thumbnail-footer'); elFooter.html(innerHTML); elFooter.append( $('<div/>').html(title) .addClass('file-footer-caption') .append($('<div/>').addClass('file-thumb-progress') .addClass('hide') .html('<div class="progress"><div class="progress-bar progress-bar-success progress-bar-striped active" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width:0%;">0%</div></div>') ) ); el.append(elImage); el.append(elFooter); return el; } function readFiles(evt) { var files = evt.target.files; //console.log(files.length); if (!files) { alert("文件不支持"); return; } for (var i = 0; i < files.length; i++) { //alert(files[i]); var drawX = 0; var drawY = 0; var imgele = new Image(); var thesrc = window.URL.createObjectURL(files[i]); imgele.src = thesrc; imgele.onload = function() { var randId = _getRandomString(5); var scale = null; //计算长宽比 var maxHeight = 800; var maxWidth = 1024; var privewWidth = 200; var privewHeight = 0; scale = imgele.height / imgele.width; if (imgele.width <= maxWidth && imgele.height <= maxHeight) { drawX = imgele.width; drawY = imgele.height; //privewHeight = 200 * scale; } else { if (scale < 1) { drawX = maxWidth; drawY = Math.ceil(maxWidth * scale); } else { drawY = maxHeight; drawX = Math.ceil(maxHeight / scale); } } var canvas = document.createElement("canvas"); canvas.setAttribute("width", drawX); canvas.setAttribute("height", drawY); canvas.innerHTML = "你的浏览器不支持"; var cxt = canvas.getContext("2d"); cxt.drawImage(this, 0, 0, drawX, drawY); var dataurl = canvas.toDataURL('image/jpg'); $('.file-preview-thumbnails').append(createPreviewEl(randId, i, dataurl, '')); $('.kv-file-upload').click(function(event) { uploadOneImg($(this).attr('randid')); }); $('.kv-file-remove').click(function(event) { var id=$(this).attr('randid'); $('#preview-' + id).remove(); }); } } } </script> </body> </html>
实现UI效果如下图
有0条评论