最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JavaScript實(shí)現(xiàn)批量將txt文件轉(zhuǎn)為pdf

 更新時(shí)間:2025年08月22日 08:17:27   作者:JYeontu  
這篇文章主要為大家詳細(xì)介紹了如何使用JavaScript實(shí)現(xiàn)批量將txt文件轉(zhuǎn)為pdf,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下

最近遇到了這樣一個(gè)場(chǎng)景,需要將很多的txt文件轉(zhuǎn)成pdf文件,一個(gè)一個(gè)手動(dòng)轉(zhuǎn)換不僅累、效率還不高,于是便寫了這么一個(gè)插件來(lái)解放自己,可以一鍵批量進(jìn)行自動(dòng)轉(zhuǎn)換~

功能說(shuō)明

這個(gè)插件的核心目標(biāo)是「降低 txt 轉(zhuǎn) pdf 的操作成本」,支持單文件轉(zhuǎn)換和多文件批量轉(zhuǎn)換。

1. 單文件轉(zhuǎn)換

針對(duì)「偶爾需要轉(zhuǎn)換單個(gè) txt 文件」的場(chǎng)景,支持手動(dòng)選擇指定的.txt文件,自定義輸出PDF的保存目錄。轉(zhuǎn)換后的PDF會(huì)自動(dòng)添加標(biāo)題、段落縮進(jìn)、頁(yè)眉(文件名)和頁(yè)腳(頁(yè)碼),排版符合中文閱讀習(xí)慣,無(wú)需后續(xù)手動(dòng)調(diào)整格式。

2. 多文件批量轉(zhuǎn)換

針對(duì)「大量txt文件需要統(tǒng)一處理」的場(chǎng)景,只需選擇存放txt文件的目錄,插件會(huì)自動(dòng)掃描目錄下所有.txt文件(忽略其他格式),按文件名順序批量轉(zhuǎn)換,并將所有PDF輸出到指定目錄。

功能實(shí)現(xiàn)

1. 命令行交互:獲取用戶配置

通過(guò)命令行獲取關(guān)鍵信息:是轉(zhuǎn)換單個(gè)文件還是批量轉(zhuǎn)換?文件/目錄在哪里?PDF要存到哪里?這里用到了@jyeontu/j-inquirer(基于inquirer的增強(qiáng)庫(kù)),支持可視化選擇文件和目錄,比手動(dòng)輸入路徑更直觀。

實(shí)現(xiàn)邏輯分為兩步:

第一步:選擇轉(zhuǎn)換模式

彈出選項(xiàng)列表,讓用戶選擇「單文件轉(zhuǎn)換」或「批量轉(zhuǎn)換」,不同模式對(duì)應(yīng)不同的后續(xù)交互——單文件需要選具體的.txt文件,批量轉(zhuǎn)換需要選存放txt的目錄。

第二步:獲取路徑信息

根據(jù)選擇的模式,動(dòng)態(tài)生成路徑選擇項(xiàng):?jiǎn)挝募J斤@示「文件選擇器」,批量模式顯示「目錄選擇器」,最后統(tǒng)一讓用戶選擇PDF的輸出目錄。

關(guān)鍵代碼片段(簡(jiǎn)化版):

const getConfig = async () => {
  // 選擇轉(zhuǎn)換模式
  const actionType = await new inquirer([
    { type: "list", name: "action", message: "請(qǐng)選擇操作", choices: ["單文件轉(zhuǎn)換", "批量轉(zhuǎn)換"] }
  ]).prompt();

  // 動(dòng)態(tài)生成路徑選擇項(xiàng)
  const options = [];
  if (actionType.action === "單文件轉(zhuǎn)換") {
    options.push({
      type: "file", name: "txtFilePath", message: "選擇txt文件", dirname: process.cwd(), pathType: "absolute"
    });
  } else {
    options.push({
      type: "folder", name: "txtDir", message: "選擇txt目錄", dirname: process.cwd(), pathType: "absolute"
    });
  }
  // 統(tǒng)一選擇PDF輸出目錄
  options.push({
    type: "folder", name: "pdfFilePath", message: "選擇PDF輸出目錄", dirname: process.cwd(), pathType: "absolute"
  });

  const answers = await new inquirer(options).prompt();
  return { ...actionType, ...answers };
};

交互效果類似這樣:

? 請(qǐng)選擇操作: 批量轉(zhuǎn)換
? 選擇txt目錄: E:\文檔\txt文件
? 選擇PDF輸出目錄: E:\文檔\PDF文件

用戶只需通過(guò)鍵盤上下鍵和回車鍵,就能完成所有配置,無(wú)需記憶復(fù)雜命令。

2. 文件轉(zhuǎn)換:txt轉(zhuǎn)pdf的核心邏輯

txt轉(zhuǎn)pdf的核心挑戰(zhàn)是「保留排版樣式」——直接將文本內(nèi)容寫入PDF會(huì)導(dǎo)致格式混亂(比如沒(méi)有段落、沒(méi)有縮進(jìn)),因此采用「HTML中間層」方案:先將txt內(nèi)容轉(zhuǎn)換為帶樣式的HTML,再用html-pdf-node將HTML渲染為PDF。

整個(gè)轉(zhuǎn)換流程分為3步:

第一步:讀取txt內(nèi)容

fs-extrareadFile方法異步讀取txt文件,同時(shí)指定編碼為utf-8,確保中文內(nèi)容不會(huì)亂碼。

const content = await fs.readFile(txtFilePath, 'utf-8');

第二步:生成帶樣式的HTML

將txt中的換行符拆分為段落,過(guò)濾空行,添加中文排版樣式(首行縮進(jìn)2字符、行高1.8、字體為微軟雅黑),同時(shí)加入標(biāo)題、頁(yè)眉頁(yè)腳占位符。
比如將txt中的"第一部分:項(xiàng)目概述\n\n這是項(xiàng)目的基本介紹。"轉(zhuǎn)換為:

<div class="title">項(xiàng)目概述</div>
<p style="text-indent:2em;">第一部分:項(xiàng)目概述</p>
<p style="text-indent:2em;">這是項(xiàng)目的基本介紹。</p>

第三步:HTML渲染為PDF

html-pdf-node加載HTML文件(先創(chuàng)建臨時(shí)HTML文件,避免內(nèi)存溢出),配置PDF參數(shù):A4格式、2cm邊距、顯示頁(yè)眉頁(yè)腳,最后將渲染后的PDF緩沖區(qū)寫入指定路徑。

關(guān)鍵代碼片段(簡(jiǎn)化版):

async convertSmallFile(content, fileName, pdfFilePath) {
  // 生成HTML
  const htmlContent = this.generateHTML(content, fileName);
  const tempHtmlPath = path.join(__dirname, "temp.html");
  await fs.writeFile(tempHtmlPath, htmlContent);

  try {
    // 配置PDF選項(xiàng)
    const options = {
      format: "A4",
      margin: { top: "2cm", right: "2cm", bottom: "2cm", left: "2cm" },
      headerTemplate: `<div style="text-align:center; color:#666;">${fileName}</div>`,
      footerTemplate: `<div style="text-align:center; color:#666;">第 <span class="pageNumber"></span> 頁(yè)</div>`
    };
    // 渲染PDF
    const buffer = await htmlpdf.generatepdf({ url: `file://${tempHtmlPath}` }, options);
    await fs.writeFile(pdfFilePath, buffer);
  } finally {
    // 清理臨時(shí)文件
    await fs.remove(tempHtmlPath);
  }
}

3. 大文件分割:避免內(nèi)存溢出

如果遇到幾千頁(yè)的大文件(比如中長(zhǎng)篇小說(shuō)),直接轉(zhuǎn)換會(huì)導(dǎo)致Node.js內(nèi)存溢出(默認(rèn)單進(jìn)程內(nèi)存限制較低)。因此需要添加「大文件分段處理」邏輯:當(dāng)txt文件字符數(shù)超過(guò)50萬(wàn)時(shí),自動(dòng)拆分為多個(gè)片段,每個(gè)片段生成獨(dú)立的「部分PDF」,最后合并為單個(gè)文件。

  • 第一步:按換行符拆分文本將txt內(nèi)容按\n拆分為行數(shù)組,確保每個(gè)片段的末尾都是完整的行。
  • 第二步:控制片段大小循環(huán)將行添加到當(dāng)前片段,當(dāng)當(dāng)前片段字符數(shù)接近30萬(wàn)(閾值)時(shí),保存當(dāng)前片段并開(kāi)始新片段。
  • 第三步:生成片段PDF每個(gè)片段生成對(duì)應(yīng)的PDF(文件名帶_part1、_part2后綴),同時(shí)記錄片段路徑,為后續(xù)合并做準(zhǔn)備。

關(guān)鍵代碼片段(簡(jiǎn)化版):

splitContent(content, maxLength) {
  const segments = [];
  const lines = content.split("\n");
  let currentSegment = "";

  for (const line of lines) {
    if ((currentSegment + line + "\n").length > maxLength && currentSegment) {
      segments.push(currentSegment.trim());
      currentSegment = line + "\n";
    } else {
      currentSegment += line + "\n";
    }
  }
  if (currentSegment.trim()) segments.push(currentSegment.trim());
  return segments;
}

4. 文件合并:將分段PDF整合成一個(gè)

分段生成的「部分PDF」需要合并為單個(gè)文件,才符合用戶的使用習(xí)慣。這里用到了pdf-lib(輕量級(jí)PDF處理庫(kù)),支持加載、復(fù)制、合并PDF頁(yè)面,且兼容性良好。

合并邏輯分為3步:

  • 第一步:檢查是否存在已生成的片段先判斷所有「部分PDF」是否已存在(比如上次轉(zhuǎn)換到一半中斷了),如果全部存在,直接合并無(wú)需重新生成,實(shí)現(xiàn)「斷點(diǎn)續(xù)轉(zhuǎn)」。
  • 第二步:復(fù)制PDF頁(yè)面創(chuàng)建一個(gè)空的PDF文檔,循環(huán)加載每個(gè)「部分PDF」,復(fù)制其中的所有頁(yè)面到空文檔中。
  • 第三步:保存合并后的PDF將合并后的PDF寫入最終路徑,同時(shí)刪除所有「部分PDF」,避免冗余文件殘留。

關(guān)鍵代碼片段(簡(jiǎn)化版):

async mergeExistingParts(partFiles, outputPath) {
  const mergedpdf = await PDFLib.PDFDocument.create();
  for (const partFile of partFiles) {
    const partBuffer = await fs.readFile(partFile);
    const partpdf = await PDFLib.PDFDocument.load(partBuffer);
    // 復(fù)制頁(yè)面到合并文檔
    const copiedPages = await mergedpdf.copyPages(partpdf, partpdf.getPageIndices());
    copiedPages.forEach(page => mergedpdf.addPage(page));
  }
  // 保存合并結(jié)果
  const mergedBytes = await mergedpdf.save();
  await fs.writeFile(outputPath, mergedBytes);
  // 清理部分文件
  partFiles.forEach(file => fs.remove(file));
}

工具使用

目前該工具已經(jīng)打包發(fā)布到npm上,可以直接使用命令安裝。

安裝

npm install -g jyeontu

目前該工具中集成了很多實(shí)用的功能,具體可以輸入命令jyeontu -h查看。

使用

需要使用 txt轉(zhuǎn)pdf功能可以按以下步驟操作。

jyeontu file

選擇txt轉(zhuǎn)pdf

后續(xù)根據(jù)提示進(jìn)行操作即可~

源碼地址

這個(gè)工具的完整源碼已開(kāi)源,支持直接克隆使用,也歡迎大家提Issue或PR改進(jìn)功能~

Gitee gitee.com/zheng_yongtao/jyeontu-cli.git

GitHub github.com/yongtaozheng/jyeontu-cli.git

到此這篇關(guān)于JavaScript實(shí)現(xiàn)批量將txt文件轉(zhuǎn)為pdf的文章就介紹到這了,更多相關(guān)JavaScript txt轉(zhuǎn)pdf內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • webpack DllPlugin xxx is not defined解決辦法

    webpack DllPlugin xxx is not defined解決辦法

    這篇文章主要介紹了webpack DllPlugin xxx is not defined解決辦法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12
  • Javascript的表單與驗(yàn)證-非空驗(yàn)證

    Javascript的表單與驗(yàn)證-非空驗(yàn)證

    JavaScript 可用來(lái)在數(shù)據(jù)被送往服務(wù)器前對(duì) HTML 表單中的這些輸入數(shù)據(jù)進(jìn)行驗(yàn)證。本文給大家介紹javascript的表單與驗(yàn)證-非空驗(yàn)證,對(duì)javascript表單驗(yàn)證相關(guān)知識(shí)感興趣的朋友一起學(xué)習(xí)吧
    2016-03-03
  • js獲取字符串最后一位方法匯總

    js獲取字符串最后一位方法匯總

    文章匯總了4種js獲取字符串最后一位字符的方法,并附上示例說(shuō)明,非常簡(jiǎn)單實(shí)用,這里推薦給大家
    2014-11-11
  • 扒一扒JavaScript 預(yù)解釋

    扒一扒JavaScript 預(yù)解釋

    這篇文章主要介紹了JavaScript 預(yù)解釋,包含帶var關(guān)鍵字預(yù)解釋、帶function關(guān)鍵字預(yù)解釋,需要的朋友可以參考下
    2015-01-01
  • Next.js應(yīng)用轉(zhuǎn)換為TypeScript方法demo

    Next.js應(yīng)用轉(zhuǎn)換為TypeScript方法demo

    這篇文章主要為大家介紹了Next.js應(yīng)用轉(zhuǎn)換為TypeScript方法demo,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • Aptana調(diào)試javascript圖解教程

    Aptana調(diào)試javascript圖解教程

    用Aptana軟件來(lái)調(diào)試javascript的方法,一般情況下大家都使用firefox瀏覽器+firebug來(lái)調(diào)試的。
    2009-11-11
  • javascript下高性能字符串連接StringBuffer類

    javascript下高性能字符串連接StringBuffer類

    使用StringBuffer類比使用加號(hào)節(jié)省50%左右的時(shí)間,大家對(duì)于大數(shù)據(jù)的連接最好使用這個(gè)方法。
    2010-08-08
  • JavaScript中的高級(jí)函數(shù)

    JavaScript中的高級(jí)函數(shù)

    在JavaScript中,函數(shù)的功能十分強(qiáng)大,除了函數(shù)相關(guān)的基礎(chǔ)知識(shí)外,掌握一些高級(jí)函數(shù)并應(yīng)用起來(lái),不僅能讓JS代碼看起來(lái)更為精簡(jiǎn),還可以提升性能,本文是小編總結(jié)的一些常用的、重要的函數(shù)
    2018-01-01
  • JavaScript中的連續(xù)賦值問(wèn)題實(shí)例分析

    JavaScript中的連續(xù)賦值問(wèn)題實(shí)例分析

    這篇文章主要介紹了JavaScript中的連續(xù)賦值問(wèn)題,結(jié)合實(shí)例形式分析了javascript賦值語(yǔ)句以及連續(xù)賦值操作相關(guān)用法與操作注意事項(xiàng),需要的朋友可以參考下
    2019-07-07
  • js實(shí)現(xiàn)的點(diǎn)擊數(shù)量加一可操作數(shù)據(jù)庫(kù)

    js實(shí)現(xiàn)的點(diǎn)擊數(shù)量加一可操作數(shù)據(jù)庫(kù)

    這篇文章主要介紹了js如何實(shí)現(xiàn)的點(diǎn)擊數(shù)量加一操作數(shù)據(jù)庫(kù),需要的朋友可以參考下
    2014-05-05

最新評(píng)論

东丽区| 综艺| 南部县| 泗水县| 阳江市| 龙游县| 浪卡子县| 廉江市| 土默特右旗| 鹿邑县| 无极县| 东乌珠穆沁旗| 内黄县| 大荔县| 南平市| 永和县| 大埔区| 石渠县| 内乡县| 彭阳县| 铜山县| 霍州市| 团风县| 青铜峡市| 舒城县| 监利县| 祥云县| 旬邑县| 涪陵区| 利辛县| 禄劝| 汽车| 木兰县| 安远县| 青川县| 台东县| 托里县| 临夏市| 公主岭市| 麦盖提县| 连城县|