CococCreator跨域访问资源服务器[经验分享]

PC浏览器测试有效
写在博客园里自己搬过来
原文点击(图文)

需求与思路
项目上线前有一个需求

游戏资源需要存放在cdn上

而游戏入口一般是通过运营渠道的服务器进入(服务器A)

玩家需要通过服务器A的游戏页面请求资源服务器B的游戏资源

这样就产生了跨域问题

(版本ccc1.3.3)转载请注明原文地址http://www.cnblogs.com/billyrun/articles/7029221.html

具体来说问题可能有以下两个

1.浏览器跨域(本文解决)

2.WebGL模式禁止跨域(没有遇到,可能是引擎避开了这个问题)

网页技术处理跨域问题有多种解决方案

这里通过修改服务端响应头header

eg:

复制代码
//任意ip均不受跨域限制

header(‘Access-Control-Allow-Origin:*’);

//指定IP如服务器A不受跨域限制

header(‘Access-Control-Allow-Origin: http(s)://yourdomain(or IP):port’);
复制代码
原理和思路大概就这么多

实现起来要小费一番周折

一方面要搭建服务器模拟资源服务器

另一方面要修改Creator引擎js源码

NodeJS搭建资源服务器
下载NodeJS并安装express

编写服务端程序代码如下

复制代码
var express = require(‘express’);
var app = express();
app.use(express.static(‘public’));

// 设置跨域头部
app.all(’’, function(req, res, next) {
res.header(“Access-Control-Allow-Origin”, "
");
res.header(“Access-Control-Allow-Headers”, “X-Requested-With”);
res.header(“Access-Control-Allow-Methods”,“PUT,POST,GET,DELETE,OPTIONS”);
res.header(“X-Powered-By”,’ 3.2.1’)
res.header(“Content-Type”, “application/json;charset=utf-8”);
next();
});

// 主页输出 “Hello World”
app.get(’/’, function (req, res) {
console.log(“主页 GET 请求”);
res.send(‘Hello GET’);
})

// 返回图片
app.get(’/image’, function(req, res) {
res.sendfile(__dirname + ‘/runoob-logo.png’);
})

// 启动服务
var server = app.listen(3000, function () {

var host = server.address().address
var port = server.address().port
console.log("应用实例,访问地址为 ", (new Date()).toLocaleString(), port)

})
复制代码

命令行中键入node [路…径]app.js 启动服务程序

打开浏览器后,即如上图所示

修改图片下载模块
首先找到下载模块

engine/cocos2d/core/load-pipeline/downloader.js

复制代码
function downloadImage(item, callback, isCrossOrigin, img) {
void 0 === isCrossOrigin && (isCrossOrigin = true);
var url = urlAppendTimestamp(item.url);
img = img || new Image();
isCrossOrigin && “file:” !== window.location.protocol ? img.crossOrigin = “anonymous” : img.crossOrigin = null;
if (img.complete && img.naturalWidth > 0 && img.src === url) {
callback(null, img);
} else {
function loadCallback() {
img.removeEventListener(“load”, loadCallback);
img.removeEventListener(“error”, errorCallback);
callback(null, img);
}
function errorCallback() {
img.removeEventListener(“load”, loadCallback);
img.removeEventListener(“error”, errorCallback);
“https:” !== window.location.protocol && img.crossOrigin && “anonymous” === img.crossOrigin.toLowerCase() ? downloadImage(item, callback, false, img) : callback(“Load image (” + url + “) failed”);
}
img.addEventListener(“load”, loadCallback);
img.addEventListener(“error”, errorCallback);
//img.src = url;
if(url.indexOf(“testSprite”) >= 0)
url = “http://localhost:3000/image
img.src = url;
cc.log(“test3 downloadImage” , url)
}
}
复制代码
if(url.indexOf(“testSprite”) >= 0)
url = “http://localhost:3000/image

这两行是我自己加的,等下加载testSprite时,我们强行加载跨域的另一个资源(用以测试跨域加载图片)

原本的url形如res/raw-assets/Texture/HelloWorld.png

上线cdn时只需要拼接完整url即可,如http://xx.xx.xx.xx/ + url

生成修改后的js引擎
这里需要参考官方文档http://www.cocos.com/docs/creator/advanced-topics/engine-customization.html

然而目前我还没弄好!

js引擎文件改写之后,需要重新生成cocos2d-js.js文件

网页中完全依靠该文件而非engine目录下的零散文件提供引擎支持

若环境尚未配置不能自动生成cocos2d-js.js文件

也可以手动修改!

首先打包发布webmobile

在打包的路径下找到build\web-mobile\cocos2d-js.js

并修改其中的downloadImage方法

注意:先发布运行,再修改,再刷新

测试跨域加载效果
测试场景放置一个按钮

点击回调加载testSprite,就像downloadImage方法里修改的那样

会去加载跨域资源

var node = new cc.Node(),sprite = node.addComponent(cc.Sprite)
cc.loader.loadRes(“testSprite.png” , cc.SpriteFrame , function(err , sp){
sprite.spriteFrame = sp
})
node.parent = this.node

测试成功!

可以看到图片正常显示

ResponseHeader里面可以看到添加的头部信息

若将app.js其中跨域的部分注释掉

可以看到原本跨域带来的问题

复制代码
/app.all(’’, function(req, res, next) {
res.header(“Access-Control-Allow-Origin”, "");
res.header(“Access-Control-Allow-Headers”, “X-Requested-With”);
res.header(“Access-Control-Allow-Methods”,“PUT,POST,GET,DELETE,OPTIONS”);
res.header(“X-Powered-By”,’ 3.2.1’)
res.header(“Content-Type”, “application/json;charset=utf-8”);
next();
});
/
复制代码
Access to Image at ‘http://localhost:3000/image’ from origin ‘http://localhost:7456’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘http://localhost:7456’ is therefore not allowed access.
CCTexture2D.js:858

Uncaught DOMException: Failed to execute ‘texImage2D’ on ‘WebGLRenderingContext’: The cross-origin image at http://localhost:3000/image may not be loaded.
at cc_Texture2D.handleLoadedTexture (http://localhost:7456/build/cocos2d-js.js:43009:28)
at Loader.loadImage (http://localhost:7456/build/cocos2d-js.js:35660:17)
at Loader.handle (http://localhost:7456/build/cocos2d-js.js:35702:26)
at Loader.asyncFlow [as flowIn] (http://localhost:7456/build/cocos2d-js.js:36171:22)
at http://localhost:7456/build/cocos2d-js.js:36179:37
at http://localhost:7456/build/cocos2d-js.js:35580:37
at HTMLImageElement.loadCallback (http://localhost:7456/build/cocos2d-js.js:35415:21)

最后说一句,真心不得不学一点服务端的东西~

参考文献

跨域相关

http://blog.csdn.net/flower46273736/article/details/62889077

http://forum.cocos.com/t/url/42848/4

http://forum.cocos.com/t/h5/42703

nodejs相关

http://www.runoob.com/nodejs/nodejs-express-framework.html

7赞

node.js作为后台,按楼主的方式修改了,但是response header并没有跨域的设置,求解

mark