nodejs收集指定目录下图片,检索当前项目是否被引用

const fs = require("fs");
const node_path = require("path");
/**
 * 数组去重
 * @param {*} arr
 */
const distinct = (arr) => {
  return Array.from(new Set(arr));
};

class cleanImg {
  constructor({
    imgFilePath, // 存放图片文件夹的路径
    srcFilePath, // src文件夹的路径(源代码所在目录)
    writeFilePath, // uselessImg.json 文件目录 (把需要删除的图片路径集合放到 uselessImg.json 文件下)
  }) {
    this.imgsFilePath = [];
    imgFilePath.forEach((item) => {
      this.imgsFilePath.push(node_path.resolve(__dirname, item));
    });

    this.srcFilePath = node_path.resolve(__dirname, srcFilePath);
    this.writeFilePath = node_path.resolve(__dirname, writeFilePath);
    this.imgFileList = []; //存放图片文件路径的数组
    this.srcFileList = []; //文件路径的数组
    this.hasImgFlieList = []; // 包含图片的文件数组
    this.uselessImg = []; // 没有被使用过的图片
    this.imgBeUsedInTheFile = []; // 在文件中使用过的图片集合
    this.dirs = [...this.imgsFilePath];
    this.srcDirs = [this.srcFilePath];
  }
  /**
   * 判断是不是图片
   * @param {String} str 字符串
   */
  isImage(str) {
    return /\.(png|jpg|gif|jpeg|webp|svg)/.test(str);
  }
  /**
   * 根据路径获取图片名称
   * @param {String} path 图片路径
   */
  getImgNameByPath(path) {
    var filename = "";
    //提供特定于平台的路径片段分隔符:
    // Windows 上是 \
    // POSIX 上是 /
    // 例如,在 POSIX 上:
    // 'foo/bar/baz'.split(path.sep); // ['foo', 'bar', 'baz']
    var slashNum = path.split(path.sep)[0]; // ['D:\\sss\\sss\\ss\\a.png']
    if (slashNum.indexOf("\\") > 0) {
      // console.log(slashNum.indexOf("\\"), "slashNum.indexOf( \\ )");
      slashNum = slashNum.replace(/\\/g, "/"); // ['D:/sss/sss/ss/a.png']
    }
    slashNum = slashNum.split("/");
    // console.log(slashNum, "getImgNameByPath return slashNum");
    if (slashNum.length > 0) {
      filename = "/" + slashNum[slashNum.length - 1];
    } else {
      filename = "";
    }
    console.log(filename, "getImgNameByPath return filename");
    return filename;
  }
  /**
   * 处理某个类目下所有文件及目录
   * @param files 文件。也可能是目录
   * @param file_path 文件或目录的上级目录
   * @param callback 一个目录或文件的判断结果的回调
   * @param allFilesDoneCallback 所有文件处理完成后的回调函数
   */
  forFiles(files, file_path, callback, allFilesDoneCallback) {
    var arrlength = files.length;
    if (!files || files.length == 0) {
      allFilesDoneCallback(file_path);
      return;
    }
    files.forEach(function (e, i) {
      var fullFilePath = node_path.join(file_path, e);

      fs.stat(fullFilePath, function (err, stat) {
        var result = {
          isDir: false,
          isFile: true,
          file: fullFilePath,
        };

        if (stat.isDirectory()) {
          result.isDir = true;
          result.isFile = false;
        } else {
          result.isDir = false;
          result.isFile = true;
        }
        //回调
        callback(result);
        arrlength--;
        //判断是否处理完毕
        if (arrlength == 0) {
          //回调所有文件处理完毕
          allFilesDoneCallback(file_path);
        }
      });
    });
  }

  /**
   * 处理单个目录
   * @param dirPath 目录路径
   * @param watchDir 监控的目录列表
   * @param callback 当目录处理完毕后的回调函数
   */
  forDir(dirPath, watchDir, callback) {
    var that = this;
    fs.readdir(dirPath, function (err, files) {
      var subFiles = [];
      that.forFiles(
        files,
        dirPath,
        function (result) {
          //如果是目录,继续执行forDir并在之前将目录添加到watchDir
          //如果是文件,放入subFiles中
          if (result.isDir) {
            watchDir.push(result.file);
            that.forDir(result.file, watchDir, callback);
          } else {
            subFiles.push(result.file);
          }
        },
        function (processedDirPath) {
          //文件全部处理完毕后,执行回调函数通知指定目录遍历完毕,但不包括子目录
          callback(processedDirPath, subFiles);
        }
      );
    });
  }

  /**
   * 遍历处理多个类目
   * @param dirs 多个类目列表
   * @param doneCallback 处理完成的回调
   */
  forDirs(dirs, doneCallback) {
    var that = this;
    var copiedDirs = dirs.slice(0);
    var watchDir = [];
    var allFiles = [];
    copiedDirs.forEach(function (path) {
      watchDir.push(path);
      //回调函数中判断watchDir长度是否为0,如为0,表示所有的目录及其子目录处理完毕了,通知最外层处理完毕
      //并将返回的文件信息合并
      that.forDir(path, watchDir, function (processedDirPath, subFiles) {
        allFiles = allFiles.concat(subFiles);
        // console.log('%s 处理完成',processedDirPath);
        watchDir.splice(watchDir.indexOf(processedDirPath), 1);
        if (watchDir.length == 0) {
          doneCallback(allFiles);
        }
      });
    });
  }

  /**
   * 获取所有图片的路径
   */
  getImgFilePath() {
    return new Promise((resolve, reject) => {
      this.forDirs(this.dirs, function (fileList) {
        resolve(fileList);
      });
    });
  }

  /**
   * 获取src目录下所有文件的路径
   */
  getFilePath() {
    return new Promise((resolve, reject) => {
      this.forDirs(this.srcDirs, function (fileList) {
        resolve(fileList);
      });
    });
  }

  /**
   * 把需要删除的图片路径集合放到 uselessImg.json 文件下,方便查看
   */
  creatUselessImgFile() {
    fs.writeFile(
      this.writeFilePath + "/uselessImg.json",
      JSON.stringify(this.uselessImg),
      function (err) {
        if (err) {
          return console.log(err);
        }
        console.log("The file was saved!");
      }
    );
  }
  /**
   * 找出没有用到的图片集合
   */
  findUselessImgFile() {
    let copeImgFileList = [...this.imgFileList]; // cope 一份图片列表
    this.imgFileList.forEach((item) => {
      // 图片
      let imgName = this.getImgNameByPath(item);
      // console.log(imgName,'findUselessImgFile imgName');
      this.hasImgFlieList.forEach((path) => {
        //文件
        let fileContent = fs.readFileSync(path, "utf8");
        var otherStatus = /[\u4e00-\u9fa5]|\W|\s/g.test(imgName) && fileContent.indexOf(encodeURIComponent(imgName)) >= 0 || fileContent.indexOf(encodeURI(imgName)) >= 0;
        if (fileContent.indexOf(imgName) >= 0 || otherStatus) {
          let index = copeImgFileList.indexOf(item);
          index >= 0 && copeImgFileList.splice(index, 1);
          this.imgBeUsedInTheFile.push(item);
        }
      });
    });
    this.imgBeUsedInTheFile = distinct(this.imgBeUsedInTheFile); //去重
    this.uselessImg = [];
    copeImgFileList.forEach((item) => {
      console.log(item, "----------copeImgFileList");
      if (this.isImage(item)) {
        console.log(item, "----------uselessImg");
        this.uselessImg.push(item);
      }
    });
  }
  /**
   * 找出有使用图片的文件集合
   */
  findUsedImgFile() {
    this.srcFileList.forEach((path) => {
      let fileContent = fs.readFileSync(path, "utf8");
      this.isImage(fileContent.toString()) && this.hasImgFlieList.push(path);
    });
  }
  /**
   * 删除无用图片
   */
  removeUselessImg() {
    this.uselessImg.forEach((path) => {
      if (this.isImage(path)) {
        fs.unlink(path, (err) => {
          if (err) throw err;
        });
      }
    });
  }
  async main() {
    this.imgFileList = await this.getImgFilePath(); // 获取所有图片的路径
    this.srcFileList = await this.getFilePath(); // 获取指定目录下所有文件的路径

    console.log("共有图片:", this.imgFileList.length);
    console.log("共有文件:", this.srcFileList.length);

    this.findUsedImgFile(); // 找出有使用图片的文件集合

    console.log("包含图片的文件有:", this.hasImgFlieList.length);

    this.findUselessImgFile(); // 找出没有用到的图片

    console.log("使用过的图片:", this.imgBeUsedInTheFile.length);
    console.log("没有被使用过的图片:", this.uselessImg.length);

    this.creatUselessImgFile(); //创建uselessImg.json
    this.removeUselessImg(); // 删除无用的图片
  }
}
 
const cleanInstanvce = new cleanImg({
  imgFilePath: './src/static/img/', // 存放图片文件夹的路径
  srcFilePath: './src', // src文件夹的路径(源代码所在目录)
  writeFilePath: './cleanImgHistory' // uselessImg.json 文件目录 (把需要删除的图片路径集合放到 uselessImg.json 文件下)
})

cleanInstanvce.main()

gitee地址

你可能感兴趣的:(javascript,node.js)