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

本文介绍了在微信小程序中创建ZIP压缩包的场景及解决方案。由于小程序仅提供解压ZIP API,作者通过引入JSZip库并进行适配,实现了ZIP文件的创建和写入。代码示例和开发环境下的查看方法也一并给出。
摘要由CSDN通过智能技术生成

场景

微信小程序只提供了解压ZIP的API,并没有提供创建ZIP的方法。
当我们想把自己处理好的保存,打包ZIP保存下来时就需要自己实现了。

分享代码片段

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

在这里插入图片描述

导入 JSZip

首先需要 jszip

const JSZip = require('../lib/jszip.min');
const fs = wx.getFileSystemManager();

jszip 在微信小程序无法直接跑。要处理一下。把 setImmediate 全部替换为 setTimeout
在这里插入图片描述

创建ZIP文件

/**
 * 文件打包为 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);
  }
}

追加写入文件

/**
 * 追加写入文件
 * @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();  
    });
  }
}

测试方法

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)
    }
  }

测试效果

在这里插入图片描述
保存 ZIP 懒得开真机调试录动图了。功能是OK的。

开发环境查看生成的 zip

  1. 先打开开发环境的文件系统所指向的目录
    在这里插入图片描述
  2. 找到 ${wx.env.USER_DATA_PATH} 对应的目录
    在这里插入图片描述
  3. 根据我们自定的路径找到生成的测试文件
    在这里插入图片描述

参考资料

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

评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

笑虾

多情黯叹痴情癫。情癫苦笑多情难

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值