本文章的目的

  • Cocos Creator WEB平台如何上传文件
  • Cocos Creator WEB平台如何下载

H5平台如何把本地文件上传到内存中

首先利用 HTML 中的 input 把文本文件上传到内存中,

/**
 * 上传一个文件
 * @param {data: string[]} callback 下标0: 表示文件的名字, 下标1:表示文件的内容
 */
static readFilSync(callback: (data: any) => void) {
    let fileMap = {};
    let readFile = function (files, index) {
        if (index >= files.length) {
            callback && callback(fileMap);
            return;
        }
        let reader = new FileReader();//这是核心,读取操作就是由它完成.
        reader["fileName"] = files[index]["name"];
        reader["webkitRelativePath"] = files[index]["webkitRelativePath"]
        reader.readAsText(files[index]);//读取文件的内容,也可以读取文件的URL
        reader.onload = function (data) {
            let results = reader["webkitRelativePath"].split("/");
            results.splice(0, 1);
            let fileName = results.join("/");
            fileMap[`${fileName}`] = this.result;
            readFile(files, ++index);
        };
    };
    let tmpSelectFile = function (data) {
        readFile(data.currentTarget.files, 0);
    };
    let fileInput = document.getElementById("fileInput");
    if (!fileInput) {
        fileInput = document.createElement("input");
        fileInput.setAttribute("id", "fileInput");
        fileInput.setAttribute("type", "file");
    }
    fileInput.addEventListener('change', tmpSelectFile);
    fileInput.click();
}

如果有多个文件的话,上面的代码肯定满足不了需求。可以给input标签增加相应 multiple 的属性,让其支持上传多个文件

fileInput.setAttribute("multiple", "multiple");

H5平台如何把内存中的数据下载到本地

利用HTML5中的Blob对象用于组织和存放即将下载的数据

在利用 document对象来操作 HMTL a 标签来下载文件

/**
 * 下载一个文件到本地
 * @param {string} fileName 文件的名字 
 * @param {string} fileObj 文件的内容
 */
static writeFile(fileName, fileObj) {
    let textFileAsBlob = new Blob([fileObj], { type: 'application/json' });
    let downloadLink = document.createElement("a");
    downloadLink.download = fileName;
    downloadLink.innerHTML = "Download File";
    if (window.webkitURL != null) {
        // Chrome allows the link to be clicked
        // without actually adding it to the DOM.
        downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);
    }
    else {
        // Firefox requires the link to be added to the DOM
        // before it can be clicked.
        downloadLink.href = window.URL.createObjectURL(textFileAsBlob);
        //  downloadLink.onclick = destroyClickedElement;
        downloadLink.style.display = "none";
        document.body.appendChild(downloadLink);
    }
    downloadLink.click();
}

H5平台如何把内存中的多条数据打包成zip并下载到本地

首先利用 npm 命令 去下载jszip

npm install jszip --save
npm install @types/jszip --save

先利用 jszip 把内存中的多条数据打包成一个zip数据包

再利用 Blob 对象组织即将要下载的数据

最后用HTML中的 a 标签 把数据下载下来

/**
 * 把多个文件写入一个zip压缩包,并下载到本地
 * @param {  {[key: string]: string} } zipObj  {}["文件名字"] =    文件内容字符串
 * @param zipName 压缩文件的名字
 */
static writeZipAsync(zipObj: { [key: string]: string }, zipName) {
    let JSZip = require("jszip");
    var zip = new JSZip();
    for (let key in zipObj) {
        zip.file(key, zipObj[key]);
    }
    zip.generateAsync({ type: "blob" }).then(function (content) {
        let textFileAsBlob = new Blob([content], { type: 'application/json' });
        let downloadLink = document.createElement("a");
        downloadLink.download = zipName;
        downloadLink.innerHTML = "Download File";
        if (window.webkitURL != null) {
            // Chrome allows the link to be clicked
            // without actually adding it to the DOM.
            downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);
        }
        else {
            // Firefox requires the link to be added to the DOM
            // before it can be clicked.
            downloadLink.href = window.URL.createObjectURL(textFileAsBlob);
            //  downloadLink.onclick = destroyClickedElement;
            downloadLink.style.display = "none";
            document.body.appendChild(downloadLink);
        }
        downloadLink.click();
    });
}

H5平台如何把本地的zip文件读取到内存中

首先利用 HTML 中的 input 把文本文件上传到内存中,
再利用 jszip 把上传的文件内容解压出来

/**
 * 读取一个zip 压缩文件
 * @param {data: string[]} callback 下标0: 表示文件的名字, 下标1:表示文件的内容
 */
static readZipSync(callback: (data: any) => void) {
    let fileMap = {};
    let readFile = function (files, index) {
        let keys = Object.keys(files);
        if (index >= keys.length) {
            callback && callback(fileMap);
            return;
        }
        files[keys[index]].async("string").then((data) => {
            fileMap[files[keys[index]].name] = data;
            readFile(files, ++index);  
        })
    };
    let tmpSelectFile = function (data) {
        let reader = new FileReader();//这是核心,读取操作就是由它完成.
        reader["fileName"] = data.currentTarget.files[0]["name"];
        reader["webkitRelativePath"] = data.currentTarget.files[0]["webkitRelativePath"]
        reader.readAsArrayBuffer(data.currentTarget.files[0]);//读取文件的内容,也可以读取文件的URL
        reader.onload = function (data) {
            let JSZip = require('jszip');
            let  zipfile = new JSZip();
            zipfile.loadAsync(this.result).then((zip) => {
                readFile(zip.files, 0);
            }); 
        };
    };
    let fileInput = document.getElementById("fileInput");
    if (!fileInput) {
        fileInput = document.createElement("input");
        fileInput.setAttribute("id", "fileInput");
        fileInput.setAttribute("type", "file");
    }
    fileInput.addEventListener('change', tmpSelectFile);
    fileInput.click();
}