Skip to content

Commit 31f9207

Browse files
committed
修复因iframe跨域而导致的单图无法上传的BUG
1 parent 2413226 commit 31f9207

File tree

1 file changed

+121
-167
lines changed

1 file changed

+121
-167
lines changed

_src/plugins/simpleupload.js

+121-167
Original file line numberDiff line numberDiff line change
@@ -1,173 +1,127 @@
11
/**
22
* @description
3-
* 简单上传:点击按钮,直接选择文件上传
4-
* @author Jinqn
5-
* @date 2014-03-31
3+
* 简单上传:点击按钮,直接选择文件上传。
4+
* 原 UEditor 作者使用了 form 表单 + iframe 的方式上传
5+
* 但由于同源策略的限制,父页面无法访问跨域的 iframe 内容
6+
* 导致无法获取接口返回的数据,使得单图上传无法在跨域的情况下使用
7+
* 这里改为普通的XHR上传,兼容到IE10+
8+
* @author HaoChuan9421 <hc199421@gmail.com>
9+
* @date 2018-12-20
610
*/
7-
UE.plugin.register('simpleupload', function (){
8-
var me = this,
9-
isLoaded = false,
10-
containerBtn;
11-
12-
function initUploadBtn(){
13-
var w = containerBtn.offsetWidth || 20,
14-
h = containerBtn.offsetHeight || 20,
15-
btnIframe = document.createElement('iframe'),
16-
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;';
17-
18-
domUtils.on(btnIframe, 'load', function(){
19-
20-
var timestrap = (+new Date()).toString(36),
21-
wrapper,
22-
btnIframeDoc,
23-
btnIframeBody;
24-
25-
btnIframeDoc = (btnIframe.contentDocument || btnIframe.contentWindow.document);
26-
btnIframeBody = btnIframeDoc.body;
27-
wrapper = btnIframeDoc.createElement('div');
28-
29-
wrapper.innerHTML = '<form id="edui_form_' + timestrap + '" target="edui_iframe_' + timestrap + '" method="POST" enctype="multipart/form-data" action="' + me.getOpt('serverUrl') + '" ' +
30-
'style="' + btnStyle + '">' +
31-
'<input id="edui_input_' + timestrap + '" type="file" accept="image/*" name="' + me.options.imageFieldName + '" ' +
32-
'style="' + btnStyle + '">' +
33-
'</form>' +
34-
'<iframe id="edui_iframe_' + timestrap + '" name="edui_iframe_' + timestrap + '" style="display:none;width:0;height:0;border:0;margin:0;padding:0;position:absolute;"></iframe>';
35-
36-
wrapper.className = 'edui-' + me.options.theme;
37-
wrapper.id = me.ui.id + '_iframeupload';
38-
btnIframeBody.style.cssText = btnStyle;
39-
btnIframeBody.style.width = w + 'px';
40-
btnIframeBody.style.height = h + 'px';
41-
btnIframeBody.appendChild(wrapper);
42-
43-
if (btnIframeBody.parentNode) {
44-
btnIframeBody.parentNode.style.width = w + 'px';
45-
btnIframeBody.parentNode.style.height = w + 'px';
46-
}
47-
48-
var form = btnIframeDoc.getElementById('edui_form_' + timestrap);
49-
var input = btnIframeDoc.getElementById('edui_input_' + timestrap);
50-
var iframe = btnIframeDoc.getElementById('edui_iframe_' + timestrap);
51-
52-
domUtils.on(input, 'change', function(){
53-
if(!input.value) return;
54-
var loadingId = 'loading_' + (+new Date()).toString(36);
55-
var params = utils.serializeParam(me.queryCommandValue('serverparam')) || '';
56-
57-
var imageActionUrl = me.getActionUrl(me.getOpt('imageActionName'));
58-
var allowFiles = me.getOpt('imageAllowFiles');
59-
60-
me.focus();
61-
me.execCommand('inserthtml', '<img class="loadingclass" id="' + loadingId + '" src="' + me.options.themePath + me.options.theme +'/images/spacer.gif" title="' + (me.getLang('simpleupload.loading') || '') + '" >');
62-
63-
function callback(){
64-
try{
65-
var link, json, loader,
66-
body = (iframe.contentDocument || iframe.contentWindow.document).body,
67-
result = body.innerText || body.textContent || '';
68-
json = (new Function("return " + result))();
69-
link = me.options.imageUrlPrefix + json.url;
70-
if(json.state == 'SUCCESS' && json.url) {
71-
loader = me.document.getElementById(loadingId);
72-
loader.setAttribute('src', link);
73-
loader.setAttribute('_src', link);
74-
loader.setAttribute('title', json.title || '');
75-
loader.setAttribute('alt', json.original || '');
76-
loader.removeAttribute('id');
77-
domUtils.removeClasses(loader, 'loadingclass');
78-
me.fireEvent("contentchange"); // HaoChuan9421
79-
} else {
80-
showErrorLoader && showErrorLoader(json.state);
81-
}
82-
}catch(er){
83-
showErrorLoader && showErrorLoader(me.getLang('simpleupload.loadError'));
84-
}
85-
form.reset();
86-
domUtils.un(iframe, 'load', callback);
87-
}
88-
function showErrorLoader(title){
89-
if(loadingId) {
90-
var loader = me.document.getElementById(loadingId);
91-
loader && domUtils.remove(loader);
92-
me.fireEvent('showmessage', {
93-
'id': loadingId,
94-
'content': title,
95-
'type': 'error',
96-
'timeout': 4000
97-
});
98-
}
99-
}
100-
101-
/* 判断后端配置是否没有加载成功 */
102-
if (!me.getOpt('imageActionName')) {
103-
errorHandler(me.getLang('autoupload.errorLoadConfig'));
104-
return;
105-
}
106-
// 判断文件格式是否错误
107-
var filename = input.value,
108-
fileext = filename ? filename.substr(filename.lastIndexOf('.')):'';
109-
if (!fileext || (allowFiles && (allowFiles.join('') + '.').indexOf(fileext.toLowerCase() + '.') == -1)) {
110-
showErrorLoader(me.getLang('simpleupload.exceedTypeError'));
111-
return;
112-
}
113-
114-
domUtils.on(iframe, 'load', callback);
115-
form.action = utils.formatUrl(imageActionUrl + (imageActionUrl.indexOf('?') == -1 ? '?':'&') + params);
116-
form.submit();
117-
});
118-
119-
var stateTimer;
120-
me.addListener('selectionchange', function () {
121-
clearTimeout(stateTimer);
122-
stateTimer = setTimeout(function() {
123-
var state = me.queryCommandState('simpleupload');
124-
if (state == -1) {
125-
input.disabled = 'disabled';
126-
} else {
127-
input.disabled = false;
128-
}
129-
}, 400);
130-
});
131-
isLoaded = true;
132-
});
133-
134-
btnIframe.style.cssText = btnStyle;
135-
containerBtn.appendChild(btnIframe);
136-
}
137-
138-
return {
139-
bindEvents:{
140-
'ready': function() {
141-
//设置loading的样式
142-
utils.cssRule('loading',
143-
'.loadingclass{display:inline-block;cursor:default;background: url(\''
144-
+ this.options.themePath
145-
+ this.options.theme +'/images/loading.gif\') no-repeat center center transparent;border:1px solid #cccccc;margin-right:1px;height: 22px;width: 22px;}\n' +
146-
'.loaderrorclass{display:inline-block;cursor:default;background: url(\''
147-
+ this.options.themePath
148-
+ this.options.theme +'/images/loaderror.png\') no-repeat center center transparent;border:1px solid #cccccc;margin-right:1px;height: 22px;width: 22px;' +
149-
'}',
150-
this.document);
151-
},
152-
/* 初始化简单上传按钮 */
153-
'simpleuploadbtnready': function(type, container) {
154-
containerBtn = container;
155-
me.afterConfigReady(initUploadBtn);
156-
}
157-
},
158-
outputRule: function(root){
159-
utils.each(root.getNodesByTagName('img'),function(n){
160-
if (/\b(loaderrorclass)|(bloaderrorclass)\b/.test(n.getAttr('class'))) {
161-
n.parentNode.removeChild(n);
162-
}
163-
});
164-
},
165-
commands: {
166-
'simpleupload': {
167-
queryCommandState: function () {
168-
return isLoaded ? 0:-1;
169-
}
170-
}
11+
UE.plugin.register('simpleupload', function() {
12+
var me = this,
13+
containerBtn,
14+
timestrap = (+new Date()).toString(36);
15+
16+
function initUploadBtn() {
17+
var w = containerBtn.offsetWidth || 20,
18+
h = containerBtn.offsetHeight || 20,
19+
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;';
20+
21+
containerBtn.innerHTML = '<form id="edui_form_' + timestrap + '" enctype="multipart/form-data" style="' + btnStyle + '">' +
22+
'<input id="edui_input_' + timestrap + '" type="file" accept="image/*" name="' + me.options.imageFieldName + '"style="' + btnStyle + '" />' +
23+
'</form>'
24+
25+
var form = document.getElementById('edui_form_' + timestrap)
26+
var input = document.getElementById('edui_input_' + timestrap)
27+
28+
input.addEventListener('change', function(event) {
29+
if (!input.value) return;
30+
var loadingId = 'loading_' + (+new Date()).toString(36);
31+
var imageActionUrl = me.getActionUrl(me.getOpt('imageActionName'));
32+
var params = utils.serializeParam(me.queryCommandValue('serverparam')) || '';
33+
var action = utils.formatUrl(imageActionUrl + (imageActionUrl.indexOf('?') == -1 ? '?' : '&') + params);
34+
var allowFiles = me.getOpt('imageAllowFiles');
35+
me.focus();
36+
me.execCommand('inserthtml', '<img class="loadingclass" id="' + loadingId + '" src="' + me.options.themePath + me.options.theme + '/images/spacer.gif" title="' + (me.getLang('simpleupload.loading') || '') + '" >');
37+
38+
function showErrorLoader(title) {
39+
if (loadingId) {
40+
var loader = me.document.getElementById(loadingId);
41+
loader && domUtils.remove(loader);
42+
me.fireEvent('showmessage', {
43+
'id': loadingId,
44+
'content': title,
45+
'type': 'error',
46+
'timeout': 4000
47+
});
48+
}
49+
}
50+
/* 判断后端配置是否没有加载成功 */
51+
if (!me.getOpt('imageActionName')) {
52+
showErrorLoader(me.getLang('autoupload.errorLoadConfig'));
53+
return;
54+
}
55+
// 判断文件格式是否错误
56+
var filename = input.value,
57+
fileext = filename ? filename.substr(filename.lastIndexOf('.')) : '';
58+
if (!fileext || (allowFiles && (allowFiles.join('') + '.').indexOf(fileext.toLowerCase() + '.') == -1)) {
59+
showErrorLoader(me.getLang('simpleupload.exceedTypeError'));
60+
return;
61+
}
62+
63+
var xhr = new XMLHttpRequest()
64+
xhr.open('post', action, true)
65+
if (me.options.headers && Object.prototype.toString.apply(me.options.headers) === "[object Object]") {
66+
for (var key in me.options.headers) {
67+
xhr.setRequestHeader(key, me.options.headers[key])
68+
}
69+
}
70+
xhr.onload = function() {
71+
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
72+
var res = JSON.parse(xhr.responseText)
73+
var link = me.options.imageUrlPrefix + res.url;
74+
75+
if (res.state == 'SUCCESS' && res.url) {
76+
loader = me.document.getElementById(loadingId);
77+
loader.setAttribute('src', link);
78+
loader.setAttribute('_src', link);
79+
loader.setAttribute('title', res.title || '');
80+
loader.setAttribute('alt', res.original || '');
81+
loader.removeAttribute('id');
82+
domUtils.removeClasses(loader, 'loadingclass');
83+
me.fireEvent("contentchange");
84+
} else {
85+
showErrorLoader(res.state);
86+
}
87+
} else {
88+
showErrorLoader(me.getLang('simpleupload.loadError'));
89+
}
90+
};
91+
xhr.onerror = function() {
92+
showErrorLoader(me.getLang('simpleupload.loadError'));
93+
};
94+
xhr.send(new FormData(form));
95+
form.reset();
96+
})
97+
}
98+
99+
return {
100+
bindEvents: {
101+
'ready': function() {
102+
//设置loading的样式
103+
utils.cssRule('loading',
104+
'.loadingclass{display:inline-block;cursor:default;background: url(\'' +
105+
this.options.themePath +
106+
this.options.theme + '/images/loading.gif\') no-repeat center center transparent;border:1px solid #cccccc;margin-right:1px;height: 22px;width: 22px;}\n' +
107+
'.loaderrorclass{display:inline-block;cursor:default;background: url(\'' +
108+
this.options.themePath +
109+
this.options.theme + '/images/loaderror.png\') no-repeat center center transparent;border:1px solid #cccccc;margin-right:1px;height: 22px;width: 22px;' +
110+
'}',
111+
this.document);
112+
},
113+
/* 初始化简单上传按钮 */
114+
'simpleuploadbtnready': function(type, container) {
115+
containerBtn = container;
116+
me.afterConfigReady(initUploadBtn);
117+
}
118+
},
119+
outputRule: function(root) {
120+
utils.each(root.getNodesByTagName('img'), function(n) {
121+
if (/\b(loaderrorclass)|(bloaderrorclass)\b/.test(n.getAttr('class'))) {
122+
n.parentNode.removeChild(n);
171123
}
124+
});
172125
}
126+
}
173127
});

0 commit comments

Comments
 (0)