下载地址:https://ueditor.baidu.com/website/download.html
官方文档地址:http://fex.baidu.com/ueditor/
我下载的是1.4.3.3 Jsp版本utf-8,其他版本的编辑器部分应该是一致的,只是后台对接的部分不同。
上面这一部分地址的设置是设置服务器的统一接口路径
但其实我是没有用到的,因为我对图片上传的地址做了额外的设置:
var myUEditor = UE.getEditor('ueditor-container');
UE.Editor.prototype._bkGetActionUrl = UE.Editor.prototype.getActionUrl;
// 对上传图片的地址做特殊设置
UE.Editor.prototype.getActionUrl = function(action) {
if (action == 'uploadimage' || action == 'uploadscrawl') {
return 'http://img.XXXXXXX.com/imgserver/front/uploadImagesByUEditor'; //在这里返回我们实际的上传图片地址
} else {
return this._bkGetActionUrl.call(this, action);
}
}
解压官网下载的压缩包,直接打开index.html,点开关于上传的按钮(图片上传、附件上传)都会报错:
“请求后台配置项http错误,上传功能将不能正常使用!”
如下图所示:
查看了下源码,大致原理就是:
如果需要使用上传功能的话,就需要让后端新写一个接口返回一个json(这个json数据就是在jsp文件夹下的config.json),编辑器要获取到这个json才算是请求后台配置项成功,才可以正常使用上传功能。
查看了一下这个config.json文件,发现是关于一些文件大小的限制,上传字段名,完全静态,所以其实这部分直接写在前端,无需从后台请求也是可以的,而且这样也不用麻烦后台小哥哥(但不知道是否有安全问题,可能我的理解比较浅显)。
以下是修改步骤(修改一小部分源代码):
打开ueditor.all.js文件,大概是8082行:
setTimeout(function(){
// 修改这个setTimeout里面的内容
try{
me.options.imageUrl && me.setOpt('serverUrl', me.options.imageUrl.replace(/^(.*[\/]).+([\.].+)$/, '$1controller$2'));
var configUrl = me.getActionUrl('config'),
isJsonp = utils.isCrossDomainUrl(configUrl);
/* 发出ajax请求 */
me._serverConfigLoaded = false;
configUrl && UE.ajax.request(configUrl,{
'method': 'GET',
'dataType': isJsonp ? 'jsonp':'',
'onsuccess':function(r){
try {
//这部分是请求数据成功后执行的逻辑,咱们直接给config赋值,然后直接执行这部分逻辑即可。
var config = isJsonp ? r:eval("("+r.responseText+")");
utils.extend(me.options, config);
me.fireEvent('serverConfigLoaded');
me._serverConfigLoaded = true;
} catch (e) {
showErrorMsg(me.getLang('loadconfigFormatError'));
}
},
'onerror':function(){
showErrorMsg(me.getLang('loadconfigHttpError'));
}
});
} catch(e){
showErrorMsg(me.getLang('loadconfigError'));
}
});
修改后:
setTimeout(function(){
try{
me.options.imageUrl && me.setOpt('serverUrl', me.options.imageUrl.replace(/^(.*[\/]).+([\.].+)$/, '$1controller$2'));
// 这里的config就是JSP文件夹下的config.json数据 这里根据需求做了删减,你们可以去那个文件重新粘贴。
var config = {
// "basePath":"",
"imageActionName": "uploadimage",
"imageFieldName": "upfile",
// 图片上传大小的限制:10M
"imageMaxSize": 10*1024*1024,
"imageAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"],
"imageCompressEnable": true,
"imageCompressBorder": 1600,
"imageInsertAlign": "none",
"imageUrlPrefix": "http://img.xueersipeiyou.com:8093/files",
"imagePathFormat": "/image/{yyyy}{mm}{dd}/{time}{rand:6}",
"fileActionName": "uploadfile",
"fileFieldName": "upfile",
"filePathFormat": "/ueditor/jsp/upload/file/{yyyy}{mm}{dd}/{time}{rand:6}",
"fileUrlPrefix": "",
"fileMaxSize": 51200000,
"fileAllowFiles": [
".png", ".jpg", ".jpeg", ".gif", ".bmp",
".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg",
".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid",
".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso",
".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".md", ".xml"
],
"imageManagerActionName": "listimage",
"imageManagerListPath": "/ueditor/jsp/upload/image/",
"imageManagerListSize": 10,
"imageManagerUrlPrefix": "",
"imageManagerInsertAlign": "none",
"imageManagerAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"],
"fileManagerActionName": "listfile",
"fileManagerListPath": "/ueditor/jsp/upload/file/",
"fileManagerUrlPrefix": "",
"fileManagerListSize": 10,
"fileManagerAllowFiles": [
".png", ".jpg", ".jpeg", ".gif", ".bmp",
".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg",
".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid",
".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso",
".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".md", ".xml"
]
};
utils.extend(me.options, config);
me.fireEvent('serverConfigLoaded');
me._serverConfigLoaded = true;
} catch(e){
showErrorMsg(me.getLang('loadconfigError'));
}
});
修改后,重新打开index.html,
会发现后台配置项已经配置成功,报错已经消失啦:
ps:如果觉得直接把配置写在源码里不好,可以把这个config抽离出来,放在ueditor.config.js定义,然后再在源码里引用。
虽然后台配置项已经配置成功了,不报错了,但是现在的上传功能还是不能使用的,因为后端还需要写图片/文件上传接口,这个还是不能省略的哈,所以还得往下看:
官网后端接口规范说明:http://fex.baidu.com/ueditor/#dev-request_specification
简单归纳就是上传图片/文件接口返回的格式为:
/* 要包含4个字段:
state: 请求状态,若成功则返回SUCCESS 失败则返回ERROR(只要不是SUCCESS即可)
url: 上传文件的访问路径
title: 上传后的文件名称
original: 上传前的源文件名称
*/
{
"state": "SUCCESS",
"url": "upload/demo.zip",
"title": "demo.zip",
"original": "demo.zip"
}
这部分主要说明:修改图片上传面板+修改配置(增加自定义formdata字段数据)
接下来我们要去修改images对话框(多图上传)里面的内容:
image.html
这里把不想要的面板可以去掉(我去掉了[在线管理]、[图片搜索])
<html>
<head>
<meta charset="UTF-8">
<title>ueditor图片对话框title>
<script type="text/javascript" src="../internal.js">script>
<script type="text/javascript" src="../../third-party/jquery-1.10.2.min.js">script>
<script src="../../third-party/webuploader/webuploader.min.js">script>
<link rel="stylesheet" type="text/css" href="../../third-party/webuploader/webuploader.css">
<link rel="stylesheet" href="image.css" type="text/css" />
head>
<body>
<div class="wrapper">
<div id="tabhead" class="tabhead">
<span class="tab" data-content-id="remote"><var id="lang_tab_remote">var>span>
<span class="tab focus" data-content-id="upload"><var id="lang_tab_upload">var>span>
<span class="tab" data-content-id="online"><var id="lang_tab_online">var>span>
<span class="tab" data-content-id="search"><var id="lang_tab_search">var>span>
div>
<div class="alignBar">
<label class="algnLabel"><var id="lang_input_align">var>label>
<span id="alignIcon">
<span id="noneAlign" class="none-align focus" data-align="none">span>
<span id="leftAlign" class="left-align" data-align="left">span>
<span id="rightAlign" class="right-align" data-align="right">span>
<span id="centerAlign" class="center-align" data-align="center">span>
span>
<input id="align" name="align" type="hidden" value="none"/>
div>
<div id="tabbody" class="tabbody">
<div id="remote" class="panel">
<div class="top">
<div class="row">
<label for="url"><var id="lang_input_url">var>label>
<span><input class="text" id="url" type="text"/>span>
div>
div>
<div class="left">
<div class="row">
<label><var id="lang_input_size">var>label>
<span><var id="lang_input_width"> var><input class="text" type="text" id="width"/>px span>
<span><var id="lang_input_height"> var><input class="text" type="text" id="height"/>px span>
<span><input id="lock" type="checkbox" disabled="disabled"><span id="lockicon">span>span>
div>
<div class="row">
<label><var id="lang_input_border">var>label>
<span><input class="text" type="text" id="border"/>px span>
div>
<div class="row">
<label><var id="lang_input_vhspace">var>label>
<span><input class="text" type="text" id="vhSpace"/>px span>
div>
<div class="row">
<label><var id="lang_input_title">var>label>
<span><input class="text" type="text" id="title"/>span>
div>
div>
<div class="right"><div id="preview">div>div>
div>
<div id="upload" class="panel focus">
<div id="queueList" class="queueList">
<div class="statusBar element-invisible">
<div class="progress">
<span class="text">0%span>
<span class="percentage">span>
div><div class="info">div>
<div class="btns">
<div id="filePickerBtn">div>
<div class="uploadBtn"><var id="lang_start_upload">var>div>
div>
div>
<div id="dndArea" class="placeholder">
<div class="filePickerContainer">
<div id="filePickerReady">div>
div>
div>
<ul class="filelist element-invisible">
<li id="filePickerBlock" class="filePickerBlock">li>
ul>
div>
div>
<div id="online" class="panel">
<div id="imageList"><var id="lang_imgLoading">var>div>
div>
<div id="search" class="panel">
<div class="searchBar">
<input id="searchTxt" class="searchTxt text" type="text" />
<select id="searchType" class="searchType">
<option value="&s=4&z=0">option>
<option value="&s=1&z=19">option>
<option value="&s=2&z=0">option>
<option value="&s=3&z=0">option>
select>
<input id="searchReset" type="button" />
<input id="searchBtn" type="button" />
div>
<div id="searchList" class="searchList"><ul id="searchListUl">ul>div>
div>
div>
div>
<script type="text/javascript" src="image.js">script>
body>
html>
image.js
大约在第365行,这部分是使用了FEX百度前端团队开发的一个文件上传组件webUploader,以下是我们需要研究及修改的部分:
uploader = _this.uploader = WebUploader.create({
pick: {
id: '#filePickerReady',
label: lang.uploadSelectFile
},
accept: {
title: 'Images',
extensions: acceptExtensions,
mimeTypes: 'image/*'
},
swf: '../../third-party/webuploader/Uploader.swf',
server: actionUrl,
resize: true,
// 此属性是你提交的图片的name属性值,相当于
fileVal: editor.getOpt('imageFieldName'),
duplicate: true,
fileSingleSizeLimit: imageMaxSize, // 默认 2 M
compress: editor.getOpt('imageCompressEnable') ? {
width: imageCompressBorder,
height: imageCompressBorder,
// 图片质量,只有type为`image/jpeg`的时候才有效。
quality: 90,
// 是否允许放大,如果想要生成小图的时候不失真,此选项应该设置为false.
allowMagnify: false,
// 是否允许裁剪。
crop: false,
// 是否保留头部meta信息。
preserveHeaders: true
}:false,
formData: {
'dirName':'pip'
}
});
1、配置里的 fileVal 属性是提交的图片的name属性值,
fileVal:XXX
相当于
<input type="file" name="XXX">
这个属性也是后端接口在接收这个文件时的字段名
fileVal: editor.getOpt('imageFieldName'),
这里取的是ueditor.config.js中的配置,如果需要修改可以去ueditor.config.js中修改。
2、除了传输文件,如果还想传一些其他的数据,那就需要再配置formData这个选项:
formData: {
'dirName':'pip'
}
二次开发(添加自定义按钮)-相关文档-:http://fex.baidu.com/ueditor/#dev-developer
因为我这边产品的需求是需要将上传的附件与文章分开的,而ueditor自带的附件上传功能是将附件嵌入在文章里面,所以附件上传这个功能需要重新做:
第1步,创建一个自定义的对话框:
attachment_user.html
<html>
<head>
<meta charset="UTF-8">
<title>ueditor附件对话框title>
<script type="text/javascript" src="../../../../pip_static/js/config/config.js">script>
<script type="text/javascript" src="../../third-party/jquery-1.10.2.min.js">script>
<link rel="stylesheet" href="attachment_user.css" type="text/css" />
<style>
.upload-btn{
opacity: 0;
width: 100%;
height: 100%;
display: block;
cursor: pointer;
background: rgb(255, 255, 255);
}
.upload-btn:hover{
background: rgba(0,162,212);
}
style>
head>
<body>
<div class="wrapper">
<div id="tabbody" class="tabbody">
<div id="upload" class="panel focus">
<div class="placeholder">
<label class="webuploader-pick" for="file">点击选择文件label>
<input type="file" id="file" name="file" style="opacity: 0;width: 0px;height: 0px; visibility: hidden;">
<div class="tips">附件大小不可超过200Mdiv>
div>
div>
div>
div>
<script type="text/javascript" src="attachment_user.js">script>
body>
html>
attachment.js
(function () {
function uploadFileListener(){
var fileInput = $('#file')[0];
fileInput.addEventListener('change', function () {
console.log('上传附件');
if (fileInput.files != null && fileInput.files[0] != null) {
var file = fileInput.files[0];
if (Math.ceil(file.size / 1024 / 1024) > 200) {
window.parent.layer.msg('附件大小不能超过'+ 200 +'MB',{time: 1200});
return;
}
var fileObj = fileInput.files[0];
var fd = new FormData();
fd.append('imgFile', fileObj);
fd.append("dirName", 'pip');
$.ajax({
url: '上传接口地址',
data: fd,
type: "POST",
dataType: "json",
cache: false,
processData: false,
contentType: false,
beforeSend: function(){
// $('#upload-loading').show();
},
success: function (result) {
console.log(result);
if(result.code==0){
fileInput.value = '';
window.parent.vm.files.push({
name: fileObj.name,
idName : result.data.split('/pip/')[1]
});
window.parent.layer.msg("附件上传成功", {time:1500});
window.parent.ueAttachmentDialog.close(false);
}else{
window.parent.layer.msg( result.message ||'附件上传失败,请联系管理员');
}
},
error: function(error){
alert(JSON.stringify(error));
},
complete: function(){}
});
}
});
}
uploadFileListener();
})();
第2步,注册UI组件(对话框及按钮):
UE.registerUI('dialog', function(editor, uiName){
//创建dialog
var dialog = new UE.ui.Dialog({
iframeUrl:'../../lib/ueditor/dialogs/attachment_user/attachment_user.html',
//需要指定当前的编辑器实例
editor:editor,
//指定dialog的名字
name:uiName,
//dialog的标题
title:"附件",
//指定dialog的外围样式
cssRules:"width:660px; height:420px;",
//如果给出了buttons就代表dialog有确定和取消
buttons:[
{
className:'edui-cancelbutton',
label:'关闭',
onclick:function () {
dialog.close(false);
}
}
]});
// 定义一个全局变量ueAttachmentDialog来存放dialog,
// 为了在iframe的操作中可以通过:window.parent.ueAttachmentDialog.close(false)来操作和访问父窗口的方法和变量。
window.ueAttachmentDialog = dialog;
var btn = new UE.ui.Button({
name:'add-user-attachment',
title:'添加附件',
//需要添加的额外样式,指定icon图标,这里默认使用一个重复的icon
cssRules :'background-position: -622px -40px;',
onclick:function () {
//渲染dialog
dialog.render();
dialog.open();
}
});
return btn;
}, 54); // 这个54是指自定义按钮的排在默认按钮中的index
特别说明:
定义一个全局变量window.ueAttachmentDialog来存放dialog,
这是为了在iframe的操作中可以通过:window.parent.ueAttachmentDialog.close(false)来操作和访问父窗口的方法和变量。