FileSystem API 实现文件下载器 2

1852次阅读  |  发布于5年以前

上篇文章讲到如何用 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

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,请点击这里观看。

专题「JavaScript 漫谈」的其他文章 »

Copyright© 2013-2020

All Rights Reserved 京ICP备2023019179号-8