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

news2024/11/26 20:48:37

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

  • 分享代码片段
  • 场景分析
  • 解决思路
  • 附魔脚本
  • chooseMediaZip 选择附魔后的ZIP文件
    • 相关方法
    • 测试方法
  • 参考资料

分享代码片段

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

场景分析

如果你的微信小程序需要选中 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)
        });
      });
    });
  }

在这里插入图片描述

参考资料

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1296341.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【深度学习】强化学习(二)马尔可夫决策过程

文章目录 一、强化学习问题1、交互的对象2、强化学习的基本要素3、策略(Policy)4、马尔可夫决策过程1. 基本元素2. 交互过程的表示3. 马尔可夫过程(Markov Process)4. 马尔可夫决策过程(MDP)5. 轨迹的概率计…

蓝牙物联网对接技术难点有哪些?

#物联网# 蓝牙物联网对接技术难点主要包括以下几个方面: 1、设备兼容性:蓝牙技术有多种版本和规格,如蓝牙4.0、蓝牙5.0等,不同版本之间的兼容性可能存在问题。同时,不同厂商生产的蓝牙设备也可能存在兼容性问题。 2、…

联邦多任务蒸馏助力多接入边缘计算下的个性化服务 | TPDS 2023

联邦多任务蒸馏助力多接入边缘计算下的个性化服务 | TPDS 2023 随着移动智能设备的普及和人工智能技术的发展,越来越多的分布式数据在终端被产生与收集,并以多接入边缘计算(MEC)的形式进行处理和分析。但是由于用户的行为模式与服务需求的多样,不同设备上的数据分布…

Navicat 技术指引 | 连接 GaussDB 分布式

Navicat Premium(16.3.3 Windows 版或以上)正式支持 GaussDB 分布式数据库。GaussDB 分布式模式更适合对系统可用性和数据处理能力要求较高的场景。Navicat 工具不仅提供可视化数据查看和编辑功能,还提供强大的高阶功能(如模型、结…

Django的logging-日志模块的简单使用方法

扩展阅读: Python-Django的“日志功能-日志模块(logging模块)-日志输出”的功能详解 现在有下面的Python代码: # -*- coding: utf-8 -*-def log_out_test(content_out):print(content_out)content1 "i love you01" log_out_test(content1)现…

用C++实现队列顺序结构的基本操作

//队列顺序结构的基本操作: #include"stdio.h" #include"String" #define QueueSize 100 typedef char ElemType; typedef struct { ElemType data[QueueSize]; /*保存队中元素*/int front,rear; /*队头和队尾指针*/ } SqQueue; void Init…

android项目实战之编辑器集成

引言 项目需要用到编辑器&#xff0c;采用RichEditor&#xff0c;如下效果 实现 1. 引入库2 implementation jp.wasabeef:richeditor-android:2.0.0 2. XML <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width&q…

【计算机网络】应用层电子邮件协议

一、电子邮件系统架构 电子邮件是一个典型的异步通信系统&#xff0c;发送方从UA&#xff0c;也就是邮件客户端&#xff0c;通过应用层SMTP协议&#xff0c;传输层tcp协议&#xff0c;发送给发送方的邮件服务器&#xff0c;比如使用的是163邮箱&#xff0c;163提供的SMTP服务器…

C++ day59 下一个更大元素Ⅱ 接雨水

题目1&#xff1a;503 下一个更大元素Ⅰ 题目链接&#xff1a;下一个更大元素Ⅱ 对题目的理解 返回循环数组中每个元素的下一个更大元素&#xff0c; 数字x的下一个更大元素是循环等的搜索它的最近的下一个更大的数 数组的中至少有一个元素 本题难点在于循环遍历这里&…

基于深度学习yolov5实现安全帽人体识别工地安全识别系统-反光衣识别系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 实现安全帽人体识别工地安全识别系统需要使用深度学习技术&#xff0c;特别是YOLOv5算法。下面是对基于YOLOv5实现安…

[mac系统]利用换行符查找替换^p 报错 --caption_column‘ calue ‘test‘ needs to be one of: image

报错内容 代码内容 args.image_column "image" args.caption_column "text" 问题原因&#xff1a; 训练过程需要blip文件是metadata.json格式 ​ 测试过程需要的文件是txt格式 blip.txt​ ​ 解决办法 1 利用word查找替换 用{"file_name": &…

银行卡二要素API的应用案例:从在线购物到金融投资

引言 随着互联网技术的不断发展&#xff0c;人们的金融需求也在不断增加。随之而来的是各种新型金融服务的涌现&#xff0c;让用户的金融体验更加便利快捷。其中&#xff0c;银行卡二要素API的应用&#xff0c;则为用户的金融体验和安全性提供了极大的保障。 银行卡二要素API…

【C++数据结构 | 图速通】10分钟掌握邻接矩阵 邻接表 | 快速掌握图论基础 | 快速上手抽象数据类型图

图 by.Qin3Yu 请注意&#xff1a;严格来说&#xff0c;图不是一种数据结构&#xff0c;而是一种抽象数据类型。但为了保证知识点之间的相关性&#xff0c;也将其列入数据结构专栏。 本文需要读者掌握顺序表和单链表的操作基础&#xff0c;若需学习&#xff0c;可参阅我的往期文…

数据清洗、特征工程和数据可视化、数据挖掘与建模的应用场景

1.5 数据清洗、特征工程和数据可视化、挖掘建模的应用场景 视频为《Python数据科学应用从入门到精通》张甜 杨维忠 清华大学出版社一书的随书赠送视频讲解1.5节内容。本书已正式出版上市&#xff0c;当当、京东、淘宝等平台热销中&#xff0c;搜索书名即可。内容涵盖数据科学应…

PostgreSQL从小白到高手教程 - 第38讲:数据库备份

PostgreSQL从小白到专家&#xff0c;是从入门逐渐能力提升的一个系列教程&#xff0c;内容包括对PG基础的认知、包括安装使用、包括角色权限、包括维护管理、、等内容&#xff0c;希望对热爱PG、学习PG的同学们有帮助&#xff0c;欢迎持续关注CUUG PG技术大讲堂。 第38讲&#…

企业博客SEO:优化SOP,助您提升搜索引擎可见性

企业博客是互联网时代企业与用户沟通的重要渠道之一&#xff0c;引流成本也比较低。然而&#xff0c;依然有企业会处在3种状态&#xff1a; 1. 有博客&#xff0c;但内容更新不积极或搁置 2. 有博客&#xff0c;但内容散乱 3. 根本就没有博客 如果是这几种状态&#xff0c;…

uniapp,点击选中并改变颜色,第二次点击取消选中状态

一、效果图 二、代码实现 字符串的indexOf和数组的indexOf用法一致&#xff01; arr.indexOf(item) 该方法返回某个元素在数组中的位置。若没检索到&#xff0c;则返回 -1。 关键代码&#xff1a;(通过:class绑定) :class"selectList.indexOf(sub.type) ! -1 ? right_ite…

ambari hive on Tez引擎一直卡住

hive on tez使用./bin/hive启动后一直卡住&#xff0c;无法进入命令行 使用TEZ作为Hive默认执行引擎时&#xff0c;需要在调用Hive CLI的时候启动YARN应用&#xff0c;预分配资源&#xff0c;这需要花一些时间&#xff0c;而使用MapReduce作为执行引擎时是在执行语句的时候才会…

Selenium+Unittest+HTMLTestRunner框架更改为Selenium+Pytest+Allure(二)

1 代码框架 整体项目结构如图&#xff1a; Common&#xff1a;公共库 Logs&#xff1a; 日志目录 Page&#xff1a; 页面元素 Report&#xff1a;测试报告 TestCase&#xff1a;测试用例 TestData&#xff1a; 测试数据 2 单模块运行 直接上代码&#xff1a; # -*- coding…

mysql 主从搭建、django实现读写分离、django中多redis缓存、django中使用连接池、pycharm远程linux开发

1 mysql 主从搭建 2 django实现读写分离 3 django中多redis缓存 4 django中使用连接池 5 pycharm远程linux开发 1 mysql 主从搭建 # 之前做过redis的主从&#xff0c;很简单# mysql 稍微复杂一些&#xff0c; 搭建mysql主从的目的是&#xff1f;-读写分离-单个实例并发量低&…