微信小程序 - 创建 ZIP 压缩包

微信小程序 - 创建 ZIP 压缩包

场景

微信小程序只提供了解压ZIP的API,并没有提供创建ZIP的方法。

当我们想把自己处理好的保存,打包ZIP保存下来时就需要自己实现了。

分享代码片段

不想听废话的,直接看代码
https://developers.weixin.qq.com/s/ChblKjmo7ZNd

导入 JSZip

首先需要 jszip

javascript 复制代码
const JSZip = require('../lib/jszip.min');
const fs = wx.getFileSystemManager();

jszip 在微信小程序无法直接跑。要处理一下。把 setImmediate 全部替换为 setTimeout

创建ZIP文件

javascript 复制代码
/**
 * 文件打包为 zip
 * @param {*} fileList 文件列表 [{ name: '文件名', path: '文件路径'}]
 * @param {*} zipPath  保存压缩包的路径
 * @param {*} progress 处理进度更新时:回调
 */
async function zip(fileList, zipPath, progress=res=>console.log){
  try {
    // 实例化 jszip
    var jszip = new JSZip();
    // 遍历文件列表,添加到 zip 文件列表中
    let total = fileList.length;
    fileList.forEach((file, index) => {
      jszip.file(file.name, new Uint8Array(fs.readFileSync(file.path)));
      progress({ percent: Math.round((index+1)/total) * 100, msg: `读取资源 ${index+1}/${total}` });
    });
    // 生成压缩包对象(uint8array)
    let content = await jszip.generateAsync(
      { type : JSZip.support.uint8array ? "uint8array" : "string" },
      meta => progress({ percent: Math.floor(meta.percent), msg: `创建 ZIP...` }) // { currentFile: '', percent: 100 }
    );
    // 将 arrayBuffer 形式压的缩包数据写入二进制文件,生成 zip
    progress({ percent: 0, msg: `保存 ZIP...` }); // 开始
    // 分块写入
    await appendFile({ 
      filePath: zipPath, 
      data: content.buffer, 
      encoding: 'binary', 
      progress: percent => progress({ percent: Math.floor(percent), msg: `保存 ZIP...` })
    }).then(() => {
      progress({ percent: 100, msg: `ZIP 保存完成` });
    }).catch(err => {
      console.error('写入文件失败:', err);  
    });
  } catch (err) {
    console.log(err);
  }
}

追加写入文件

javascript 复制代码
/**
 * 追加写入文件
 * @param {string} filePath     文件路径
 * @param {string} data         写入数据
 * @param {string} encoding     编码类型:默认 utf8
 * @param {number} chunkSize    写入块大小:默认 1048576 字节
 * @param {function} progress   更新进度回调
 */
function appendFile(options) { 
  let { filePath, data, encoding, chunkSize, progress } = Object.assign({
    encoding: 'utf8',     // 编码类型,默认 utf8。想写二进制用 'binary'
    chunkSize: 1048576,   // 每块大小默认 1M
    progress: console.log // 更新进度
  }, options);

  // 文件总长度
  const fileLength = data instanceof ArrayBuffer ? data.byteLength : data.length;  

  // 文件小于 chunkSize 直接写
  if(fileLength <= chunkSize){
    return new Promise((resolve, reject) => {
      try {
        resolve(fs.writeFileSync( filePath, data, encoding ));
      } catch (error) {
        reject(error);
      }      
    });
  }else{
    // 否则分块写入,并调用进度更新 callback
    return new Promise((resolve, reject) => {
      // 先写入一个空文件。(作用:有则清空,无则创建)
      fs.writeFileSync(filePath, new ArrayBuffer(0), encoding);
      // 已写入长度
      let writtenLength = 0;
      // 写入数据块
      const writeChunk = () => {
        const chunkData = data.slice(writtenLength, writtenLength + chunkSize); // 切段
        fs.appendFile({  
          filePath,         // 文件路径
          data: chunkData,  // 数据块
          encoding,         // 编码类型
          success: () => {  
            writtenLength += chunkSize; // 更新已写入长度
            progress( Math.floor((writtenLength / fileLength) * 100)); // call回调函数更新进度  
            if (writtenLength < fileLength) {  
              writeChunk();  // 继续写入下一块数据  
            } else {  
              resolve(writtenLength);  // 文件写入完成:返回写入长度
            }  
          },  
          fail: err => reject(err) 
        });  
      };
      // 继续调用写入数据块
      writeChunk();  
    });
  }
}

测试方法

javascript 复制代码
test(){
    const zipFolder = `${wx.env.USER_DATA_PATH}/test`;
    const zipPath = `${zipFolder}/hello.zip`;
    let fileList = [];
    try {
      // 先创建对应目录
      fileUtil.mkdir(zipFolder);
      // 生成测试文件
      for (let index = 0; index < 10; index++){
        let filePath = `${wx.env.USER_DATA_PATH}/test/hello${index}.txt`;
        fileList.push({ name: `hello${index}.txt`, path: filePath});
        const res = fs.writeFileSync( filePath, `测试数据${index+1}`, 'utf8' );
        console.log(res);
      }
      // 打包 zip
      fileUtil.zip(fileList, zipPath, console.log);
      // 保存 zip
      wx.saveFileToDisk({ filePath: zipPath, success: console.log, fail: console.error });
    } catch(e) {
      console.error(e)
    }
  }

参考资料

jszip:一个使用JavaScript创建、读取和编辑.zip文件的库,带有一个可爱而简单的API。

相关推荐
小蒜学长10 小时前
基于微信小程序的遇见咖啡店点餐系统设计与实现(代码+数据库+LW)
java·spring boot·后端·微信小程序·咖啡店点餐系统
光影少年1 天前
Taro 是如何解析入口配置 app.config.ts 和页面配置的?
微信小程序·小程序·typescript·reactjs·百度小程序·taro
用户788477316341 天前
门店核销闭环:小程序扫码 + .NET 幂等接口 + WPF 看板,一天能跑通
微信小程序·c#
愚公搬代码1 天前
【愚公系列】《微信小程序项目实战(AI编程+视频图解)》014-莫凡商城小程序项目视图容器组件的应用
微信小程序·小程序·ai编程
星光开发者2 天前
基于决策树随机森林算法的小说推荐系统的设计与实现-计算机毕设【课程设计】78485
vue.js·算法·微信小程序·django·php·课程设计·express
QQ_21696290962 天前
基于微信小程序的智能膳食分析系统
java·大数据·spring boot·微信小程序·小程序·旅游
QQ_21696290962 天前
基于C#(Asp.net)电竞陪玩信息管理系统的设计与实现
java·大数据·spring boot·微信小程序·c#·云计算·asp.net
m0_462803884 天前
名单制签到怎么落地:拆解“仅名单内人员签到“的配置链路与匹配逻辑
微信小程序
卓怡学长4 天前
w192基于springboot“考研情报站”微信小程序设计与实现
java·spring boot·spring·微信小程序·intellij-idea
Q26433650236 天前
【有源码】基于uni-app的旅游行程规划小程序-基于微信小程序的智慧文旅综合服务平台
java·微信小程序·小程序·uni-app·毕业设计·springboot·源代码