ueditor上传七牛经历了一个多星期,终于做的比较满意的实现了,期间踩过很多坑,就不分享这些坑了,直接说最后的成品,当然这里面还是有很多bug没有修复。具体问题大家具体分析吧。我纪录下我的结果。
首先是参考文章列表如下:
不过作者 php文件夹里面的config.json 这一句注释错误了,会导致errorHandler is not defined。各位需要注意。
我写的项目是根据iview-admin
改的后台,所以先根据 链接2在项目中引入ueditor
的双向绑定,因为VueUeditorWrap
绑定的也是实际项目public
目录下的ueditor
所以在把链接1的文件下载下来,放入public目录。具体的就不说了直接上图
ueditor放的位置,iview-admin放的是public文件夹下,如果是vue-cli放的static文件夹下
这个时候富文本编辑器应该可以显示出来了,舞台搭好了,然后才是我们的大戏。
根据链接1的文章,更改好配置后,我们发现上传图片还是会报错。如果你认真对比了链接1和链接2中的关于单图上传的代码你就会发现,2号作者也发现了这个问题。
由于ueditor使用的ueditor.all.min.js
压缩以后不好更改,所以我的做法是直接用ueditor.all.js在线压缩,然后把压缩后的内容覆盖目前的ueditor.all.min.js
内容,我的用的编辑器是vscode,使用beautify插件一键格式化ueditor.all.min.js
然后找到simpleupload
方法
如下代码替换原代码:
UE.plugin.register('simpleupload', function() {
var me = this,
containerBtn,
timestrap = (+new Date()).toString(36);//时间转换为36进制的字符串
function initUploadBtn() {
var w = containerBtn.offsetWidth || 20,
h = containerBtn.offsetHeight || 20,
btnStyle = 'display:block;width:' + w + 'px;height:' + h + 'px;overflow:hidden;border:0;margin:0;padding:0;position:absolute;top:0;left:0;filter:alpha(opacity=0);-moz-opacity:0;-khtml-opacity: 0;opacity: 0;cursor:pointer;';
var form = document.createElement('form');
var input = document.createElement('input');
form.id = 'edui_form_' + timestrap;
form.enctype = 'multipart/form-data';
form.style = btnStyle;
input.id = 'edui_input_' + timestrap;
input.type = 'file'
input.accept = 'image/*';
input.name = me.options.imageFieldName;
input.style = btnStyle;
form.appendChild(input);
containerBtn.appendChild(form);
input.addEventListener('change', function(event) {
if (!input.value) return;
var loadingId = 'loading_' + (+new Date()).toString(36);
var imageActionUrl = me.getActionUrl(me.getOpt('imageActionName'));
var params = utils.serializeParam(me.queryCommandValue('serverparam')) || '';
var action = utils.formatUrl(imageActionUrl + (imageActionUrl.indexOf('?') == -1 ? '?' : '&') + params);
var allowFiles = me.getOpt('imageAllowFiles');
me.focus();
me.execCommand('inserthtml', '');
function showErrorLoader(title) {
if (loadingId) {
var loader = me.document.getElementById(loadingId);
loader && domUtils.remove(loader);
me.fireEvent('showmessage', {
'id': loadingId,
'content': title,
'type': 'error',
'timeout': 4000
});
}
}
/* 判断后端配置是否没有加载成功 */
if (!me.getOpt('imageActionName')) {
showErrorLoader(me.getLang('autoupload.errorLoadConfig'));
return;
}
// 判断文件格式是否错误
var filename = input.value,
fileext = filename ? filename.substr(filename.lastIndexOf('.')) : '';
if (!fileext || (allowFiles && (allowFiles.join('') + '.').indexOf(fileext.toLowerCase() + '.') == -1)) {
showErrorLoader(me.getLang('simpleupload.exceedTypeError'));
return;
}
var xhr = new XMLHttpRequest()
xhr.open('post', action, true)
// console.log(action)
if (me.options.headers && Object.prototype.toString.apply(me.options.headers) === "[object Object]") {
for (var key in me.options.headers) {
xhr.setRequestHeader(key, me.options.headers[key])
}
}
// console.log(xhr.status)
xhr.onload = function() {
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
var res = JSON.parse(xhr.responseText)
var link = me.options.imageUrlPrefix + res.url;
// console.log(res)
if (res.state == 'SUCCESS' && res.url) {
// console.log(res);
loader = me.document.getElementById(loadingId);
loader.setAttribute('src', link);
loader.setAttribute('_src', link);
loader.setAttribute('title', res.title || '');
loader.setAttribute('alt', res.original || '');
loader.removeAttribute('id');
domUtils.removeClasses(loader, 'loadingclass');
me.fireEvent("contentchange");
} else {
showErrorLoader(res.state);
}
} else {
showErrorLoader(me.getLang('simpleupload.loadError'));
}
};
xhr.onerror = function() {
showErrorLoader(me.getLang('simpleupload.loadError'));
};
xhr.send(new FormData(form));
form.reset();
})
}
return {
bindEvents: {
'ready': function() {
//设置loading的样式
utils.cssRule('loading',
'.loadingclass{display:inline-block;cursor:default;background: url(\'' +
this.options.themePath +
this.options.theme + '/images/loading.gif\') no-repeat center center transparent;border:1px solid #cccccc;margin-right:1px;height: 22px;width: 22px;}\n' +
'.loaderrorclass{display:inline-block;cursor:default;background: url(\'' +
this.options.themePath +
this.options.theme + '/images/loaderror.png\') no-repeat center center transparent;border:1px solid #cccccc;margin-right:1px;height: 22px;width: 22px;' +
'}',
this.document);
},
/* 初始化简单上传按钮 */
'simpleuploadbtnready': function(type, container) {
containerBtn = container;
me.afterConfigReady(initUploadBtn);
}
},
outputRule: function(root) {
utils.each(root.getNodesByTagName('img'), function(n) {
if (/\b(loaderrorclass)|(bloaderrorclass)\b/.test(n.getAttr('class'))) {
n.parentNode.removeChild(n);
}
});
}
}
});
相当于form表单上传的方式。
这个时候关于链接1中的上传配置也要做相应的修改: controller.php
中修改如下
这个时候单图直接上传七牛的功能已经实现了,然后多图上传因为有很多bug,我就直接忽略了,不适用多图上传,其实问题很上传视频和附件的,然后小伙伴们还想使用,可以根据下面的内容自行修改。
找到video.js
我的文件目录如下
public\UEditor\dialogs\video\video.js
上传七牛首先要解决的是获取token的问题,链接1作者是自己写的生成token的办法,或者我的理解有错,我遇到的问题是token不匹配,所以我是调取后端接口生成的token。因为jsonp是可以跨域传数据,所以ajax同步的请求方式失效了
执行到这一步还是有问题的,文件虽然上传成功了,但是回显数据是有问题的,那我们继续往下看token是上传前需要获取的,这个时候我们上传成功了,但是还是会文件框还是会显示一个红条报错,那我们找一下是哪里的问题,因为ueditor是结合webuploader完成上传的,那么看uploadSuccess
这个方法,通过在代码中的不同位置console.log()
不同的内容来确定报错的位置。最后确定是try()
方法中的if()
判断出了问题,那为什么if判断为假呢,console.log(json)
发现,json的返回中并没有if判断需要的数据,那自己添加拼接一个不就行了,代码如下:
uploader.on('uploadSuccess', function (file,ret) {
var $file = $('#' + file.id);
try {
var json;
// 分片上传通过服务器合成来返回数据
if( isChunked ){
var url = editor.getActionUrl(editor.getOpt('makeFileActionName')),
isJsonp = utils.isCrossDomainUrl(url);
$.ajax({
dataType : isJsonp ? 'jsonp':'json',
async : false,
method : 'post',
data : { ctx : qiniuCtx, type : file.type, size : file.size, name:file.name, host:chunkUploadUrl},
url : url,
success:function(data) {
json = data;
}
});
}else{
var responseText = (ret._raw || ret);
json = utils.str2json(responseText);
json['state'] = 'SUCCESS';
json['url']= 'http://img.*******.com/'+ json.key;//这里需要写你自己七牛的存储空间的域名
}
// var responseText = (ret._raw || ret),
// json = utils.str2json(responseText);
if (json.state == 'SUCCESS') {
uploadVideoList.push({
'url': json.url,
'type': json.type,
'original':json.original
});
$file.append('');
} else {
$file.find('.error').text(json.state).show();
}
} catch (e) {
$file.find('.error').text(lang.errorServerUpload).show();
}
});
OK!到这里视频上传就完成了,关于视频预览无法加载的问题请参考链接3
解决办法如同视频上传七牛,小伙伴自行实践吧。vue小白一枚,如果有问题欢迎评论讨论!