微信小程序 - PC端选择ZIP文件

本文介绍了如何在微信小程序的PC端选择ZIP文件,由于wx.chooseMessageFile API在PC端不支持,作者提出了利用wx.chooseMedia API的曲线解决方案。通过在ZIP文件前添加PNG头,然后在获取文件后去除PNG头,恢复正常的ZIP文件,从而实现ZIP文件的选择和处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

场景分析

如果你的微信小程序需要选中 ZIP 包,然后解压并处理其中的文件。
对于移动端可以使用 wx.chooseMessageFile(Object object) 来实现,它支持从客户端会话选择文件。
但不幸的是PC端,并不支持此API。官方也没有给出别的API。(当然论坛里有提到一个曲线解决方案,申请个企业号,用webview实现选择文件。网上有讨论的,这里就不细聊了。)
但是对于个人号来说,这就尴尬了。一是没有权限使用webview,二是纯前端的小程序,为了选择文件还得加个服务器,有点不值当。
所以想到了一个曲线的解决方案。利用:chooseMedia

解决思路

  1. 虽然PC端不支持 wx.chooseMessageFile 但支持 wx.chooseMedia 这个API是用来选择媒体文件的,比如:视频、图片。
  2. 通过测试,直接将 zip 的扩展名改为 PNG 是无效的。因为选择后,它会检查文件头,过滤掉不符合的,最终只能拿到真实的PNG文件。
  3. 既然它是校验了文件头,那我们就给ZIP文件前加上PNG的文件名,然后通过 wx.chooseMedia 获取到文件后,再跳过我们自己的 PNG头,把剩余的ZIP部分读出来,保存为一个正常的 ZIP 文件。
  4. 然后就可以正常解压或读取 ZIP 压缩包了。

附魔脚本

PNG头加到ZIP文件前面,可以使用下面这个脚本实现。
这是附魔的bat脚本,通过在zip前添加25个字节,是PNG文件的头89504E470D0A1A0A0000000D49484452转成的base64

echo iVBORw0KGgoAAAANSUhEUg==>_________
copy /b _________ + /b %1 %~nx1.png
del /q _________

zip拖到脚本上之后,即可生成一个 xxx.zip.png 文件。

chooseMediaZip 选择附魔后的ZIP文件

const fs = wx.getFileSystemManager();

/**
 * 选择媒体附魔的ZIP
 * @param {object} options 
 */
function chooseMediaZip(options = {}){
  const defaultOptions = { 
    count: 9,                                 // 单次选择数量上限
    mediaType: ['image'],                     // 选择框支持的文件类型
    encoding: 'binary',                       // 编码类型,默认 'binary'。想写文本用 'utf8'
    folder: `${wx.env.USER_DATA_PATH}/jerry`, // 保存二进制文件的路径
    suffix: 'zip'                             // 二进制文件的扩展名
  };
  let params = {...defaultOptions, ...options};
  return wx.chooseMedia(params) // 选择 *.zip.png 文件
  .then(res=>{ // 跳过 PNG 读取出实际二进制数据
    return res.tempFiles.map(tempFile=> {
      // 跳过PNG头25字节,从26开始读取 zip 的二进制部分
      const arrayBuffer  = readFileSync(tempFile.tempFilePath, '', 26);
      console.log(arrayBuffer);
      // 写 二进制文件 到目录 path
      const file = {};
      file.name = `${Date.now()}.${suffix}`;
      file.path =`${ params.folder }/${ file.name }`;
      mkdir(params.folder); 
      writeFileSync( file.path, arrayBuffer, encoding ); // 写 二进制 文件
      return file; // {name: 'fileName', path: 'http://xxx.xxx'}
    });
  }).catch(console.error);
}

相关方法

chooseMedia 需要用到的几个方法

/**
 * 判断文件或目录是否存在
 * @param {string} path 文件或目录路径
 */
function isExist(path){
  try {
    fs.accessSync(path);
    return true;
  } catch (err) {
    console.log(`文件或目录不存在:${err.message}`);
    return false;
  }
}

/**
 * 创建目录路
 * 如果目录不存在就创建。
 * @param {string} dirPath 文件夹路径
 * @param {boolean} recursive 如果上级目录不存在,是否自动创建。默认:是
 */
function mkdir(path, recursive = true){
  if(isExist(path) == false){                       // 判断目录是否存在
    fs.mkdirSync(path, recursive);                  // 如果没有就创建
  }
}

/**
 * 写文件
 * @param {*} filePath 文件路径。要写入的文件路径 (本地路径)
 * @param {*} data 要写入的文本或二进制数据
 * @param {*} encoding 指定写入文件的字符编码。默认 binary
 */
function writeFileSync(filePath, data, encoding='binary') {  
  fs.writeFileSync(filePath, data, encoding);
}

测试方法

test(e){
    fileUtil.chooseMediaZip({ 
      count: 9,                                 // 单次选择数量上限
      mediaType: ['image'],                     // 选择框支持的文件类型
      encoding: 'binary',                       // 编码类型,默认 'binary'。想写文本用 'utf8'
      folder: `${wx.env.USER_DATA_PATH}/jerry`, // 保存二进制文件的路径
      suffix: 'zip'                             // 二进制文件的扩展名
    }).then(res => {
      res.forEach(zip => {
        fs.readZipEntry({
          'filePath': zip.path,
          'entries': 'all',
          success: res => console.log(res.entries), // zip中的文件列表
          fail: err => console.log(err)
        });
      });
    });
  }

在这里插入图片描述

分享代码片段

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

参考资料

判断文件/目录是否存在(同步版) FileSystemManager.accessSync(string path)
创建目录(同步版) FileSystemManager.mkdirSync(string dirPath, boolean recursive)
写文件(同步版) FileSystemManager.writeFileSync(string filePath, string|ArrayBuffer data, string encoding)

123个微信小程序源码: AppleMusic B站首页界面设计:附详细教程 cnode社区版 dribbble FlexLayout布局 gank HIapp IT-EBOOK leantodu LOL战绩查询 movecss效果 Railay:整体框架 redux绑定 TCP,IP长连接 todo list v2ex 一个(仿) 一元夺宝主页设计 万年历 下拉刷新,tab切换 东航订机票 事项助手 二维码生成器 云笔记 五十音图 五险一金计算 人脸检测 今日头条 仿微信DEMO 仿找事吧 仿网易云音乐 会议精灵 你画我猜 侧滑布局 健康菜谱 全屏动画滚动 分答小程序 创客+实现大量功能,推荐研究 剪刀石头布 医药网 卡卡汽车 获取用户 设备信息 同乐居商城:购物车合算 商城 图书管理系统 图文信息;欢迎页面,音乐控制 图片自适应 ,富文本解析 圆形菜单 城市切换 备忘录 外卖:实现类似锚点功能 大转盘 天气预报 妈妈课堂 家居电商 富文本解析,折线图,MD5,bluebird 小游戏-别踩白块 小熊的日记 小程序地图定位 小程序完整demo:飞翔的小鸟:canvas实现,java后(适用1221) 小程序官方Demo 小程序版2048 小程序页面生成器 康爱多微商城:学习界面设计 微票 我厨 tab 界面设计 手势解锁 掘金首页信息流 摇一摇换文章 教务系统 新浪读书 新闻客户 易打卡 表单设计 星巴克中国 智能机器人 机器人兔兔 极客学院 果库 查拼音 校内新闻大图 框架 步步高字典 水浒传 治疗师 涂鸦 滑动选项卡 滴滴公交-查公交 瀑布流布局 用户反馈组件 电商-拼团 倒计时 电影推荐 电影日历 画布:时钟 番茄时钟 百度小说 相册;处理用户信息 省市选择控件 知乎 知乎日报 知乎日报1 科学计算器 移动小商城:基于node,包含前后台 移动商城 简易计算器 网易云课堂 腾讯云小程序一站式解决方案 自定义tabbar 芒果TV 语音跟读 豆瓣图书 豆瓣电影 货币汇率 购物车 跑步 地理位置 计时器 身份证查询 车源宝 轮播图+菜单 轮播图变换 辩论倒计时 重邮 题库:选择选项,切换至下一题 首字母排序选择 高仿苹果计算器 麻将骰子:附详细教程
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

笑虾

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

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

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

打赏作者

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

抵扣说明:

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

余额充值