nodeJs生成项目文件中用到的本地图片

吐槽君 分类:javascript

作为一名前端仔,在项目开发过程中,当你需要对一个项目中的某些文件使用到的图片,全部搬运到另一个项目中时,如果不想将整个图片文件拷贝过去,通常会选择一张张图片查找后手动复制过去。如果这个页面用到了很多图片,这种做法就慢如乌龟。于是,我选择利用nodeJs实现快速地生成项目文件中用到的本地图片。

注意: 本代码例子只适用于windows系统,若想适配其他系统,请修改输出路径。

先康康最终效果:

ceshi.gif

可以发现,终端运行命令后生成了该文件中使用到的所有本地图片的文件。

PS: nodeJs神通广大,利用它可以干很多事情。

1. 初始化

新建一个copyimg.js文件,并初始化代码:

    #!/usr/bin/env node

    //引入模块
    const path = require('path');
    const fs = require('fs');

    var args = process.argv.splice(2);
    let curPath = args[0];  //想要获取图片的项目文件的绝对路径
    var outputPath = "c:\Users\Administrator\Desktop\copyimg\";  //图片文件输入路径
 

如上,我们将在终端运行node copyimg [项目文件名]生成图片文件,并将得到的图片文件保存到电脑桌面的copyimg文件夹里。

2. 获取图片文件的绝对路径

项目中的本地图片一般会以相对路径引用,例如:"../../images/button.png",我们需要将他们都转为绝对路径。
这里用到的正则如下:

    /(?<quotes>['"])(?<content>[-\w/.]+?)\.(?<suffix>png|jpg)\k<quotes>/ug
 

该正则规避了上传到CDN的图片链接,虽然没有怎么考虑到回溯的问题,但已足以使用,这里不是讨论重点。

    let imgList = [];

    toReadImg();

    //获取img绝对路径
    function getImgPath(imgRelativePath = "") {
        return path.resolve(path.dirname(curPath), imgRelativePath);
    }

    function toReadImg() {
        fs.readFile(curPath, { encoding: 'utf-8' }, (err, data) => {
            data.replace(/(?<quotes>['"])(?<content>[-\w/.]+?)\.(?<suffix>png|jpg)\k<quotes>/ug, (...args) => {
                let groups = args[args.length -1];
                let { content, suffix } = groups;
                let imgPath = getImgPath(content + '.' + suffix);
                imgList.push(imgPath);
            });

            console.log("imgList", imgList);
        });
    }
 

到这里,我们已经可以获得所有本地图片的绝对路径。运行后终端将打印出包含图片绝对路径的数组imgList

3. 获取所有图片文件和该项目文件的根路径

这一步是必要的,因为我们将要将图片复制到我们自定义的路径里,即outputPath

    //获取最长公共前缀路径
    getCommonPath = function getCommonPath (path1 = '', path2 = '', ...rest) {
        path1 = path1.replace(/[^\]+$/, '');
        if (!path2) return path1;
        path2 = path2.replace(/[^\]+$/, '');

        let base = '';
        for (let i = 0; i < path1.length && i < path2.length; i++) {
          if (path1[i] === path2[i]) {
            base += path2[i]
          } else {
            break
          }
        }
        if (rest.length) {
          return getCommonPath(base, ...rest);
        }
        return base
    };

    let commonPath = getCommonPath(curPath, ...imgList);

    console.log('commonPath: ', commonPath);
 

4. 生成图片到outputPath对应的文件夹

    imgList.forEach(imgPath => {
        writeImg(imgPath, imgPath.replace(commonPath, outputPath));
    })

    //路径尾部添加斜杠
    function addSlash(pathStr) {
        if (pathStr[pathStr.length - 1] != "\") {
            pathStr += "\"
        }
        return pathStr
    }

    //文件夹某一路径不存在时的回退处理
    function handleDirReturn(folder, dirList) {
        if (dirList.length) {
            folder = addSlash(folder) + dirList.pop();
            mkdirFolder(folder, dirList)
        }
    }

    //创建文件夹
    function mkdirFolder(folder, dirList = []) {
        try {
            fs.accessSync (folder);
            handleDirReturn(folder, dirList);
        } catch(error) {
            try {
                fs.mkdirSync(folder, 0777);
                handleDirReturn(folder, dirList);
            } catch(err) {
                let newPath = path.resolve(folder, '..');
                dirList.push(path.basename(folder));
                let num = 0;
                newPath.replace(/\/g, () => {
                    ++num;
                })
                if (num > 1) {
                    mkdirFolder(newPath, dirList);
                }
            }
        }
    }

    //生成图片
    function writeImg(oldPath, newPath) {
        let imgDir = path.resolve(newPath, '..');
        mkdirFolder(imgDir);
        fs.readFile(oldPath, function(err,originBuffer) {            //读取图片位置
            fs.writeFile(newPath, originBuffer, function(err){      //生成图片
                if (err) {
                    console.log(err)
                }
            });
        })
    }
 

至此,该功能已经实现。
当然,我们可以加一点小小的代码,使它支持自定义输出路径:

    if (args[1]) {
        outputPath = args[1];
    }
    outputPath = addSlash(outputPath);
 

这样就可以直接将A项目的图片直接复制到B项目的文件夹里来了,一步到位。

完整代码如下:

一线大厂高级前端编写,前端初中阶面试题,帮助初学者应聘,需要联系微信:javadudu

回复

我来回复
  • 暂无回复内容