微信小程序 - 文件工具类 fileUtil.js

微信小程序 - 文件工具类 fileUtil.js

const fs = wx.getFileSystemManager();

/**
 * 选择媒体附魔的ZIP
 * @param {object} options 
 */
function chooseMediaZip(options = {
    }){
   
  const defaultOptions = {
    count: 9, mediaType: ['image']};
  let params = {
   ...defaultOptions, ...options};
  return wx.chooseMedia(params) // 选择 *.zip.png 文件
  .then(res=>{
    // png 处理为 zip
    return res.tempFiles.map(file => {
   
      /* 这是附魔的bat脚本,在zip前添加了25个字节,是一个PNG文件的头:89504E470D0A1A0A0000000D49484452 转成的 base64
      echo iVBORw0KGgoAAAANSUhEUg==>_________
      copy /b _________ + /b %1 %~nx1.png
      del /q _________
      */
      // 读取zip的二进制部分
      const arrayBuffer  = readFileSync(file.tempFilePath, '', 26);
      console.log(arrayBuffer);
      // 写 zip 到目录 globalData.PATH.zippng
      const zipFile = {
   };
      zipFile.name = `${
     Date.now()}.zip`;
      zipFile.path =`${
      params.zippng }/${
      zipFile.name }`;
      mkdir(params.zippng); // 先创建目录
      writeFileSync( zipFile.path, arrayBuffer, 'binary' ); // 写 zip 文件
      return zipFile; // {name: 'fileName', path: 'http://xxx.png'}
    });
  }).catch(console.error);
}

/**
 * 选择媒体文件
 * @param {object} options 
 */
function chooseMedia(options = {
    }){
   
  const defaultOptions = {
    count: 9, mediaType: ['image']};
  return wx.chooseMedia({
   ...defaultOptions, ...options});
}

/**
 * 从聊天中选择文件
 * @param {number} _count 
 */
function chooseFile(_count){
   
  return wx.chooseMessageFile({
    count: _count })
  .then( res => {
   
    //  res 内容: {
   
    //     "errMsg":"chooseMessageFile:ok",
    //     "tempFiles":[
    //       {
   
    //         "name":"spineboy.zip",
    //         "size":273679,
    //         "time":1692946544,
    //         "path":"http://tmp/eZhBTvHhtCEN1328314d91c79395dce640b2f2aba2e7.zip",
    //         "type":"file"
    //       }
    //     ]
    //   }
    if(res.errMsg === "chooseMessageFile:ok"){
   
      return res.tempFiles;
    }else{
   
      return [];
    }
  });
}

/**
 * 获取目录结构
 * @param {string} rootPath 
 */
function ls(rootPath) {
     
  // 检查目录是否存在  
  if(!isExist(rootPath)){
   
    return [];
  }
  let list = fs.statSync(`${
     rootPath}`, true);

  if(Array.isArray(list) == false && list.isDirectory()) {
   
    return [];
  }

  // 返回一个对象包含 dirPath 目录下的文件和子目录:{'file':[], 'dir': []}
  return list.map(df => {
   
    df.type = df.stats.isFile() ? 'file' : 'dir';
    return df;
  }).reduce((result, item) => {
   
    item.path = `${
     rootPath}/${
     item.path}`;
    result[item.type].push(item);
    return result;
  }, {
   'file':[], 'dir': []});
}

/**
 * 删除文件(同步版)
 * @param {string} filePath 文件路径
 */
function unlinkSync(filePath){
   
  if(isExist(filePath) == false){
   
    console.log(`文件不存在:${
     filePath}`)
    return;
  }
  try {
   
    const res = fs.unlinkSync(filePath);
    console.log(res)
  } catch(e) {
   
    console.error(e)
  }
}

/**
 * 清空目录:包含所有子目录和文件
 * @param {string} rootPath 要清空的目录
 * @param {*} saveSelf      是否删除自己。为 false 则只清空其实的子目录和文件,但保留自己
 */
function clearDir(rootPath, saveSelf=true) {
     
  // 检查目录是否存在  
  if(!isExist(rootPath)){
   
    return;
  }

  // 获取:文件与子目录
  let group = ls(rootPath);
  if(Array.isArray(group.file) == false){
    // 如果file属性不是一个数组,说明没查到东西。是个空文件夹。
    return;
  }

  // 删除所有文件
  let p = group.file.map(f => {
   
    return new Promise((resolve, reject) => {
   
      fs.unlink({
   
        filePath: f.path,
        success: res => resolve(res),
        fail: err => reject(err)
      })
    });
  });

  // 删除全部文件后,再执行删除目录。
  Promise.all(p).then(res => {
   
    fs.rmdir({
   
      dirPath: `${
     rootPath}`,
      recursive: true,
      success: res => console.log(res),
      fail: err => console.error(err),
    });
  });
  // 上面是直接递归删除整个目录,包括自己。这里判断一下,如果需要保留根目录,就再创建一下。
  if(saveSelf){
   
    mkdir(rootPath);
  }
}

/**
 * 清空目录(同步版):包含所有子目录和文件
 * @param {string} rootPath 要清空的目录
 * @param {*} saveSelf      是否删除自己。为 false 则只清空其实的子目录和文件,但保留自己
 */
function clearDirSync(rootPath, saveSelf=true) {
     
  // 检查目录是否存在  
  if(!isExist(rootPath)){
   
    return;
  }

  // 获取:文件与子目录
  let group = ls(rootPath);
  if(Array.isArray(group.file) == false){
    // 如果file属性不是一个数组,说明没查到东西。是个空文件夹。
    return;
  }

  // 删除所有文件
  group.file.map(f => fs.unlinkSync(f.path));
  // 递归删除全部目录。
  fs.rmdirSync(rootPath, true);

  // 上面是直接递归删除整个目录,包括自己。这里判断一下,如果需要保留根目录,就再创建一下。
  if(saveSelf){
   
    mkdir(rootPath);
  }
}

/**
 * 清空目录下的文件(同步版)(只删除文件)
 * @param {string} rootPath 要清空的目录
 * @returns 被删除的文件列表
 */
function clearFilesSync(rootPath) {
     
  try {
   
    // 获取目录下的文件列表
    const files = fs.readdirSync(rootPath);
    // 删除所有文件
    files.forEach(path => fs.unlinkSync(`${
     rootPath}/${
     path}`));
    return files;
  } catch (error) {
   
    console.error(error);
  }
}

/**
 * 判断文件或目录是否存在
 * @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 {string} path 要删除的目录路径 (本地路径) 
 * @param {boolean} recursive 是否递归删除目录。如果为 true,则删除该目录和该目录下的所有子目录以及文件
 */
function rmdirSync(path, recursive=false){
   
  if(isExist(path)){
                          // 判断目录是否存在
    fs.rmdirSync(path, recursive);            // 如果存在就删除
  }
}

/**
 * 为文件名添加编号后缀
 * @param {*} fileName      原文件名
 * @param {*} suffixNumber  编号
 * @param {*} suffixLen     编号位数
 */
function addSuffixNumber(fileName, suffixNumber, suffixLen) {
   
    // 获取文件名与扩展名
    let extension = '';  
    let index = fileName.lastIndexOf('.');  
    if (index !== -1) {
     
        extension = fileName.substring(index);  
        fileName = fileName.substring(0, index);  
    }  
    // 计算后缀序号的位数  
    let suffixLength = Math.floor(Math.log10(suffixLen)) + 1;
    // 对后缀编号进行高位补零  
    let paddedSuffixNumber = String(suffixNumber).padStart(suffixLength, '0');  
    // 返回新的文件名  
    return `${
     fileName}_${
     paddedSuffixNumber}${
     extension}`;  
}

/**
 * 高位补零
 * @param {*} num       需要补零的序号
 * @param {*} count     序号所在序列中,的总数。用于计算要补几位
 * @param {*} suffixStr 自定补啥字符
 */
function padNumber(num, count=10, suffixStr='0') {
   
  // 计算后缀序号的位数  
  let suffixLength = Math.floor(Math.log10(count)) + 1;
  // 对后缀编号进行高位补零  
  return String(num).padStart(suffixLength, suffixStr);  
}

/**
 * 解析文件路径返回:{路径、全名、文件名、扩展名}
 * @param {*} filePath 文件路径
 */
function getFileInfo(filePath) {
     
  // 获取文件夹路径  
  const folderPath = filePath.substring(0, filePath.lastIndexOf('/') + 1);
  // 获取文件名  
  const fileName = filePath.substring(folderPath.length, filePath.lastIndexOf('.'));
  // 获取扩展名  
  const fileExtension = filePath.substring(filePath.lastIndexOf('.') + 1);
  return {
     
    path: folderPath,  
    fullName: `${
     fileName}.${
     fileExtension}`,
    name: fileName,  
    extension: fileExtension  
  };  
}

/**
 * 读取本地文件内容。单个文件大小上限为100M。
 * @param {*} filePath 文件路径。要读取的文件的路径 (本地路径)
 * @param {*} encoding 指定读取文件的字符编码,如果不传 encoding,则以 ArrayBuffer 格式读取文件的二进制内容
 * @param {*} position 默认从0开始读取。左闭右开区间 [position, position+length)。有效范围:[0, fileLength - 1]。单位:byte
 * @param {*} length   指定文件的长度,如果不指定,则读到文件末尾。有效范围:[1, fileLength]。单位:byte
 */
function readFileSync(filePath, encoding='', position=0, length) {
     
  return fs.readFileSync(filePath, encoding, position, length);
}

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

module.exports = {
   
  fs,
  chooseMediaZip,
  chooseMedia,
  chooseFile,
  ls,
  unlinkSync,
  clearDir,
  clearDirSync,
  clearFilesSync,
  isExist,
  mkdir,
  rmdirSync,
  addSuffixNumber,
  padNumber,
  readFileSync,
  writeFileSync
};

相关推荐

  1. 程序 - 文件工具 fileUtil.js

    2023-12-08 08:22:03       40 阅读
  2. 程序下载文件详解

    2023-12-08 08:22:03       14 阅读
  3. 程序-npm扩展工具包

    2023-12-08 08:22:03       22 阅读
  4. 程序

    2023-12-08 08:22:03       46 阅读
  5. 程序

    2023-12-08 08:22:03       21 阅读

最近更新

  1. tensorflow学习笔记(二)

    2023-12-08 08:22:03       1 阅读
  2. Typescript【网址取ID传入后端API】

    2023-12-08 08:22:03       1 阅读
  3. mongodb-数据备份和恢复

    2023-12-08 08:22:03       1 阅读
  4. 《C++20设计模式》中单例模式

    2023-12-08 08:22:03       1 阅读
  5. 数字孪生技术在智能家居中的应用

    2023-12-08 08:22:03       1 阅读
  6. 单例模式的多种实现方式及其在框架中的使用

    2023-12-08 08:22:03       1 阅读
  7. 一、Prometheus和Grafana搭建

    2023-12-08 08:22:03       1 阅读

热门阅读

  1. 第59天:django学习(八)

    2023-12-08 08:22:03       32 阅读
  2. Git初学入门指令

    2023-12-08 08:22:03       31 阅读
  3. 策略模式终极解决方案之策略机

    2023-12-08 08:22:03       30 阅读
  4. 鸿蒙(HarmonyOS)应用开发——构建页面(题目答案)

    2023-12-08 08:22:03       71 阅读
  5. 状态模式-C++实现

    2023-12-08 08:22:03       37 阅读
  6. Ansible及其优势是什么?

    2023-12-08 08:22:03       41 阅读
  7. selenium 执行js后拿不到返回值的原因

    2023-12-08 08:22:03       38 阅读
  8. 【脚本】图片-音视频-压缩文件处理

    2023-12-08 08:22:03       34 阅读