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条评论