您当前位置:lerx技术交流
本类热点
推荐阅读
文章正文
Lerx & KindEditor 4 跨域上传设置记录
2012-09-27 09:48:39
lzh

从提高服务器性能角度考虑,尽可能分离各种服务。

对于Web服务器来说,尽可能分离Web中的资源服务已是一种趋势。比如:图片、js文件、flash及用于下载的文件能尽可能放置于其它服务器,将主Web服务器减少不必要的服务。一些大的网站都采用了这种方法,最起码是有专用的图片及文件服务器。这就带来了一个跨域上传的问题。

基于上述原因,我也对lerx系统进行了此项试验(模板采有的编辑器是KindEditor 4.1.1 (2012-06-10))。历经两天,实际用时六小时,最后是意外成功。现记录如下:(注:Lerx版本必须是20120927以后的版本)

假定两个服务器的域名如下(事实上也只有同一域名下的多个子域名才可以跨域):

A ----> www.lerx.com

b ----> files.lerx.com

 

    1在主服务器A和图传服务器B上同时布署Lerx。注:数据库为同一数据库。即A和B数据完全相同。如:A的内网地址为 172.16.0.6 ,B的内网地址为 172.16.0.7 ,数据库服务器的内网地址为:172.16.0.10。A和B都连接同一数据库。

 

    2都成功后,网站后台网站基本设置确认一下。这样就生成了网站加密文件。默认是WEB-INF下的curLerxHost.jsp。

取其中之一复制到另一服务器上。然后修改资源文件将lerx.lockSecFile=false改为true。因为Lerx上传或登录是用进行身份验证的,身份验证需要与此文件进行校验比对,所以必须相同。改为true就是加锁,系统数据发生变化时不会更改些文件。

 

    3更改资源文件 resourcesApplication_zh_CN.properties 如下

lerx.cookieDomain=lerx.com      说明:当此值不为null时,lerx系统将自动认为系统采用了跨域技术。

lerx.sessionPrefixOfAdminAuthentication=admin@lerx.com@asdf

lerx.sessionPrefixOfUserAuthentication=user@lerx.com@asdf

lerx.prefixOfCookieForLogin=lerx.com_asdf

上面的asdf是任意取的。原来的servername是一定要改掉的,因为两个服务器的域名不同,不改的话,系统会自动修改servername为当前域名。

说明:上述操作要在AB两个服务器上同时进行。

 

    4进入后台,修改门户所用的模板。至articleAdd和articleEdit模块,因为这两个模块都采用了上传模块。(因数据相同,只要在一台机上修改一次就行了)

在内容最前方加入如下代码:

<script type="text/javascript">
try
{
document.domain = "lerx.com";
}
catch(e)
{
}
</script>

注意:上面的lerx.com要与步骤2中的lerx.cookieDomain的值完全相同。

 

    5同时修改模块中的KindEditor加载模块。

uploadJson : 'http://files.lerx.com/uploadForKE.action',
				fileManagerJson : 'http://files.lerx.com/kindeditor-4.1.1/jsp/file_manager_json.jsp',

 即,将上传处理动作更改为B服务器。

 

    6.  修改编辑器中的js文件:kindeditor-4.1.1/plugins/multiimage/multiimage.js(用于多文件上传)。大约447行,主要是加上B的地址,范例如下

// Update the flash url if needed
	if (!!this.settings.prevent_swf_caching) {
		this.settings.flash_url = "http://files.lerx.com"+this.settings.flash_url + (this.settings.flash_url.indexOf("?") < 0 ? "?" : "&") + "preventswfcaching=" + new Date().getTime();
	}

完毕。

在我的测试中,系统内置的上传采用跨域没有问题。而KindEditor想通过不容易。我搞了一晚上,不能成功。至第二天,好象没做什么改动,重启了两台服务器,最后发现意外成功了,自己都不清楚是哪里的操作导致成功。上面的内容是参照成功后的配置及文件内容整理出来的,供大家参考。

 

-----------------------------------------------------------------

 

重要补充:

意外成功却又意外失败!清空了一些文件,再整理时发现又恢复失败了。 花了两天,苦尽甘来,研究KindEditor源码,终于改好了。(我对javascript也是一知半解,前台的东西不是太熟悉。)至今都不明白,那天并没有采用现在的方式怎么突然成功了的!

失败的原因为:

上传后返因的数据仅仅为json类型的字符串,不存在任何其它代码。仅管上传成功了。但由于返回的页面数据与当然的frame的域不同,导致访问当前表单及表单中的任何元素都被拒绝。

解决方法如下:

在上传的脚本里加入一些html,并设置当前域与表单的域相同。示例如下:

String ymp,cookieDomain= cdm.getActionSupport().getText("lerx.cookieDomain");
					
					if (cookieDomain!=null && !cookieDomain.trim().equals("") && !cookieDomain.trim().equalsIgnoreCase("null")){
						url = SrvInf.srvUrl(request, "",
								Integer.valueOf(getText("lerx.serverPort"))) + "/" + url;
						ymp="<script type=\"text/javascript\">try"+"\n"+"{document.domain = \""+cookieDomain+"\";}catch(e){}</script>";
					}else{
						url = request.getContextPath() + "/" + url;
						ymp="";
					}

这里面还存在一个问题:就是多图片上传时不能有除json值以外的内容。因此,根据来源页来判断,如果为空,那就是flash上传。

boolean flashPost;
					String postReferer=request.getHeader("referer");
					if (postReferer==null || postReferer.trim().length()<1){	//检查来源页,如果没有就是flash上传
						flashPost=true;
					}else{
						flashPost=false;
					}

输出部分脚本如下:

obj.put("error", 0);
					obj.put("url", url);
					String outStr,objstr;
					if (flashPost){
						outStr=obj.toJSONString();
					}else{
						
						
						objstr="<div id=\"lerxjson\">"+obj.toJSONString()+"</div>";
						
						outStr="<html><body>"+ymp+objstr+"</body></html>";
					}
					
response.getWriter().write(outStr);

这里改好了,但还没结束。

修改KindEditor源码:

在KindEditor.js中的约4113行开始。像如下进行修改:

var doc = K.iframeDoc(iframe),
				pre = doc.getElementsByTagName('pre')[0],
				str = '', data;
			var jstr= doc.getElementById('lerxjson').innerHTML;
			if (jstr!=null){
				jstr=_trim(jstr);
			}
			if (pre) {
				str = pre.innerHTML;
			} else {
				str = doc.body.innerHTML;
			}
			iframe[0].src = 'javascript:false';
			
			
			try {
				if (jstr!=""){
					data = K.json(jstr);
				}else{
					data = K.json(str);
				}
			} catch (e) {
				self.options.afterError.call(self, '<!doctype html><html>' + doc.body.parentNode.innerHTML + '</html>');
			}
			if (data) {
				self.options.afterUpload.call(self, data);
			}

原理是读取json数据时要根据返回内容,读需要的元素内容。我这里用的是lerxjson。

注意:resourcesHostInf_zh_CN.properties文件中的lerx.host.current也要相同。

至此,KindEditor 4.1的跨域上传大致完成。


-----------------------------------------------------------------------------


2015.5.13补充。

有时不稳定,原本好好的,不知道经受什么折腾,发现多图片上传发生问题。最终这问题的解决办法是修改plugins/multiimage/multiimage.js。

flash文件的权限问题。改成上传服务器的swf,如下面被注释掉的一行。


---约第250行
flashUrl : imgPath + 'swfupload.swf',
//flashUrl : 'http://portalfiles.lerx.com/kindeditor-4.1.1/plugins/multiimage/images/swfupload.swf',