资讯专栏INFORMATION COLUMN

node获取指定目录下所有文件的内容生成PDF

xeblog / 1369人阅读

有个需求场景是需要把某个目录下的所有指定文件的内容生成pdf,因为是前端开发,所以就用node来干活
首先是pdf的包是用pdfkit, 这里有两个坑,第一个是生成的文件中可能会有系统无法识别的换行和空格,会被替换成莫名其妙的符号,因此在拼接完内容后,要使用 str.replace(/rn|r/g, "n")
进行过滤,第二个坑是中文字符会乱码,因此要引入中文ttf,例如
doc.font("./msyh.ttf") ;
接下来是获取所有文件内容,在一开始我是判断文件的长度来识别是否结束,但是文件获取是异步,递归的时候同时进行这么多读取操作,如何才能判断所有异步操作都已经结束了呢,答案就是我们的Promise.all啦
首先我们将fs模块的几个要用到方法promiseify化,也就是我们可以将异步操作包装在promise函数中,由于文件操作的回调函数也是作为参数传入(万能的JS),所以我们只要获取到arguments中的callback函数,并且根据成功或者失败去resolve或reject就行啦,
那么Promise.all是用来干嘛呢?
Promise.all 接收一个 promise 对象的数组作为参数,当这个数组里的所有 promise 对象全部变为resolve或 有 reject 状态出现的时候,它才会去调用 .then 方法,它们是并发执行的。也就是说我们并行执行的所有文件读取操作,可以用Promise.all来解决啦!

const fs = require("fs")
const yargs = require("yargs")
const PDF = require("pdfkit")
const readdir = promisify(fs.readdir);
const stat = promisify(fs.stat);
const readFile = promisify(fs.readFile);
const doc = new PDF();

function uuid(times = 10) {
    let g = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
        str = "";
    let len = g.length;
    for (let i = 0; i < times; i++) {
        str += g[Math.round((Math.random() * (len - 1)))];
    }
    return str;
}
let { path = "", name = uuid(), fileType = "" } = yargs.argv || {};
let str = "";

fileType = (fileType.split(",") || []).filter(item => item !== "")

function promisify(fn) {
    return function() {
        let args = Array.from(arguments);
        return new Promise(function(resolve, reject) {
            args.push(function(err, result) {
                if (err) {
                    reject(err);
                } else {
                    resolve(result);
                }
            });
            fn.apply(null, args);
        });
    }
}

function readDirRecur(file, callback) {
    return readdir(file).then(function(files) {
        files = files.map(function(filename) {
            let fullPath = `${file}/${filename}`;
            return stat(fullPath).then(function(stats) {
                let limmit = fileType.length ? fileType.find(item => filename.includes(`.${item}`)) : true;
                if (stats.isDirectory()) {
                    return readDirRecur(fullPath, callback);
                } else if (limmit) {
                    return readFile(fullPath, "utf8").then(function(data) {
                        callback(filename, data, fullPath);
                    });
                }
            })
        });
        return Promise.all(files);
    });
}
if (!path) return false;
readDirRecur(path, function(filename, data, fullPath) {
    str += data;
}).then(function() {
    str = str.replace(/
|
/g, "
");
    doc.pipe(fs.createWriteStream(`${name}.pdf`))
    doc.fontSize(10);
    doc.font("./msyh.ttf");
    doc.text(str, 50, 50);
    doc.end()
}).catch(function(err) {
    console.log(err);
});

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/108545.html

相关文章

  • 使用Node.js爬取任意网页资源并输出高质量PDF文件到本地~

    摘要:上面只爬取了京东首页的图片内容,假设我的需求进一步扩大,需要爬取京东首页中的所有标签对应的跳转网页中的所有的文字内容,最后放到一个数组中。 showImg(https://segmentfault.com/img/bVbtVeV?w=3840&h=2160); 本文适合无论是否有爬虫以及Node.js基础的朋友观看~ 需求: 使用Node.js爬取网页资源,开箱即用的配置 将爬取到的...

    seasonley 评论0 收藏0
  • 使用Node.js爬取任意网页资源并输出高质量PDF文件到本地~

    摘要:上面只爬取了京东首页的图片内容,假设我的需求进一步扩大,需要爬取京东首页中的所有标签对应的跳转网页中的所有的文字内容,最后放到一个数组中。 showImg(https://segmentfault.com/img/bVbtVeV?w=3840&h=2160); 本文适合无论是否有爬虫以及Node.js基础的朋友观看~ 需求: 使用Node.js爬取网页资源,开箱即用的配置 将爬取到的...

    xiaoxiaozi 评论0 收藏0
  • 使用Node.js爬取任意网页资源并输出高质量PDF文件到本地~

    摘要:上面只爬取了京东首页的图片内容,假设我的需求进一步扩大,需要爬取京东首页中的所有标签对应的跳转网页中的所有的文字内容,最后放到一个数组中。 showImg(https://segmentfault.com/img/bVbtVeV?w=3840&h=2160); 本文适合无论是否有爬虫以及Node.js基础的朋友观看~ 需求: 使用Node.js爬取网页资源,开箱即用的配置 将爬取到的...

    wangym 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<