Skip to content

找到未引用的图片

作者:江月迟迟
发表于:2024-12-10
字数统计:1176 字
预计阅读4分钟

介绍

小蓝在公司负责图文编辑器的开发,每次在编辑器中插入图片都会调用一次上传接口,将图片上传至服务器中,但是文章最终编辑完成时可能并未引用所有上传的图片,这就导致许多“无效文件”的产生,于是小蓝想编写一个维护脚本,定期清理那些未被引用的图片文件。

下面就请你使用 Node.js 帮助小蓝找出那些未引用的图片。

准备

开始答题前,需要先打开本题的项目代码文件夹,目录结构如下:

txt
├── articles
├── images
├── index.js
└── test.js

其中:

  • articles 是项目的文章目录。
  • images 是项目的图片目录。
  • test.js 是验证答案是否正确的工具方法。
  • index.js 是需要补充代码的 js 文件。

注意:打开环境后发现缺少项目代码,请复制下述命令至命令行进行下载。

bash
wget https://labfile.oss.aliyuncs.com/courses/16666/dist_04.zip
unzip dist_04.zip
mv dist/* ./
rm -rf dist*

目标

找到 index.js 中的 findUnlinkImages 函数,完善其中的 TODO 部分。使用 Node.js 中的 fs 等内置模块进行文件操作,查找出 images 目录下未被任何文章(articles 文件夹下的 .md 文档)引用的“无效图片”,最终需要在 findUnlinkImages 这个函数中返回包含这些“无效图片”的数组。

提示:Markdown 中插入图片语法为:![](xxxxxx.png)

提示:代码中提供了工具函数 traversalDirsearchImage 可供参考使用。

请保证封装的函数满足所有测试用例,并在终端运行以下命令:

bash
node test.js

如果你的结果正确,则在终端将会输出“测试通过”。

规定

  • 请严格按照考试步骤操作,切勿修改考试默认提供项目中的文件名称、文件夹路径、class 名、id 名、图片名等,以免造成无法判题通过。
  • 满足需求后,保持 Web 服务处于可以正常访问状态,点击「提交检测」系统会自动检测。

判分标准

  • 本题完全实现题目目标得满分,否则得 0 分

总通过次数: 1 | 总提交次数: 1 | 通过率: 100%

难度: 中等 标签: 蓝桥杯, 2023, 国赛, Web 前端, Node.js

题解

js
const path = require("path");
const fs = require("fs");
const { log } = require("console");

const articlesPath = path.resolve(__dirname, "articles");
const imagesPath = path.resolve(__dirname, "images");

const findUnlinkImages = async function () {
  const unlinkImages = []; // 未被任何 md 文件引用的图片的数组
  // TODO 请通过 Node.js 在此处继续完成代码编写

  // 1. 从articles中,提取UsedImages,使用过的图片
  let usedImages = []
  const UsedMarkdownFiles = await traversalDir(articlesPath)
  for (let file of UsedMarkdownFiles) {
    const content = await new Promise((resolve, reject) => {
      fs.readFile(path.join(articlesPath, file), "utf-8", (err, data) => {
        if (err) {
          reject(err);
          return;
        }
        resolve(data);
      });
    });
    usedImages.push(...searchImage(content));
  }

  // 2. 从images中,整理出AllImages,所有的图片
  const AllImages  = await traversalDir(imagesPath)


  // 3. 2的数组减去1的数组,返回结果
  // 取巧方法,将usedImages数组每一项字符串规范为指定格式
  // usedImages = usedImages.map(item => item.slice(10));
  // unlinkImages.push(...AllImages.filter(image => !usedImages.includes(image)));
  // 取巧方法,将usedImages数组每一项字符串规范为指定格式 END

  // 直接叠起来匹配
  // usedImages.item = ../images/62599960.png'
  // allimages.item = 62599960.png
  unlinkImages.push(...AllImages.filter(image => !usedImages.some(item => item.includes(image)) // 返回 true 为 usedImages 没有包含 image
  ));
  

  console.log(unlinkImages);
  return unlinkImages; // 此处应返回一个数组,如不明白,请仔细阅读题目
};

findUnlinkImages()

// 参考方法: 遍历文件列表
function traversalDir(path) {
  return new Promise((resolve) => {
    fs.readdir(path, async function (err, files) {
      if (!err) {
        resolve(files);
      }
    });
  });
}

let useImgs = [];
/**
 * 参考方法: 正则提取文章内的全部图片链接
 * @param {string} md 传入的markdown文本内容
 * @returns 包含所有图片链接的数组
 */
function searchImage(md) {
  const pattern = /!\[(.*?)\]\((.*?)\)/gm;
  let matcher;
  while ((matcher = pattern.exec(md)) !== null) {
    if (matcher[2].indexOf("images") !== -1) {
      // 判断存在图片,matcher[2] 即为包含的链接
      useImgs.push(matcher[2]);
    }
  }
  return useImgs;
}

module.exports = findUnlinkImages; // 请勿删除该行代码,否则影响判题!