微信小程序 - 创建 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。

相关推荐
andrsted17 小时前
作业发布、课堂检测和错题讲评,用一个小程序完成
学习·微信小程序·小程序·学习方法
汤姆yu17 小时前
基于微信小程序的家电维修预约系统
微信小程序·小程序·家电维修
软件聚导航1 天前
「聚小软 AI 助手」技术升级:从数据库检索到 RAG 知识库问答
前端·数据库·mysql·微信小程序·小程序·ai编程·rag
一叶星殇1 天前
微信小程序 Vant Popup 滚动穿透:页面级与组件级解决方案详解
微信小程序·小程序
2601_963869952 天前
【计算机毕业设计】基于微信小程序的点餐传菜系统设计与实现
微信小程序·小程序·课程设计
北漂燕郊杨哥2 天前
VS Code 安装微信小程序 MCP 介绍
vscode·微信小程序·小程序·mcp
维双云3 天前
2026微信小程序开店用哪个平台?长期稳定运营的系统选择方法
微信小程序·小程序
辛迪聊物业数字化3 天前
【智能楼宇系统有什么用?赋能园区高效 节能 安全】
经验分享·安全·微信小程序·php
Coodor3 天前
使用web也可以写NFC微信小程序拉取
前端·微信小程序·小程序·nfc拉起小程序
太阳之神aboluo4 天前
微信小程序 (1) 基础用法
微信小程序·小程序