上篇文章讲到如何用 JavaScript 编写下载器,不少小伙伴看了觉得神奇。在本篇文章里,我把之前写的一个 JS 游戏全部资源打成 Zip 包,用上回写的下载器加载,再解压到 FileSystem,最后直接运行这个游戏。也就是说只需要一次 HTTP 请求,就可以获得游戏所需的全部资源。
这篇文章,我们不会从零开始实现我们的目标,除了复用上回的下载器,还会用到 github 上两个好用的开源 JS 库,filer.js 和 zip.js。
filer.js 是对 FileSystem API 的二次封装,提供了更友好的接口和更多的功能; zip.js 提供了解压 Zip 文件的功能。zip.js 源码里的 sjis.js 文件是用来处理日文字符,可以去掉。这两个库的具体使用方法,可以直接去各自的 github 主页查看。
首先,我们还是通过 XHR 下载所需的 Zip 包,指定 responseType 为 arraybuffer。把下载到的数据包装为 Uint8Array,交给 zip.js 解压,这部分代码如下:
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.onreadystatechange = function() {
if (this.readyState == 4) {
if (this.response != null) {
var result = Zip.inflate(new Uint8Array(this.response));
console.log(result);
}
}
};
xhr.responseType = 'arraybuffer';
xhr.send();
这样,Zip 包就被解压为下面这样格式的数据了:
ZipData 包含很多信息,从命名来看,files 对象中应该只包含文件,但实际上如上图所示,「res/」这样的目录也混在其中,不过我们可以简单地通过最后一个字符来过滤掉它们。每个 file 对象的 data 属性存放的是压缩数据,调用对象的 inflate() 方法会返回这个文件的原始数据。
接下来,我们申请 FileSystem 使用权限,遍历 files 对象,并在 FileSystem 中按照 Zip 包内的目录结构保存文件。这部分代码使用 filer.js 实现很简单,filer.js 提供的 mkdir() 方法可以递归创建多级目录,类似 linux 的「mkdir -p」。另外,FileSystem Api 中操作文件都是异步操作,为了使用方便,我们可以基于 promise 做二次封装。这部分代码不贴了,可以直接看最后的 Demo。
在所有文件都写入完成后,我们获得入口文件(index.html)在 FileSystem 中的地址,直接 location 跳转就可以运行这个游戏了:
filer.create('index.html', false, function(file) {
location.href = file.toURL();
});
完整的 Demo,请点击这里观看。
Copyright© 2013-2020
All Rights Reserved 京ICP备2023019179号-8