pdfmake 中文教程

1. 项目概述

pdfmake 是一个功能强大的 JavaScript 库,用于生成 PDF 文档。它提供了简单易用的 API,允许开发者在 Node.js 或浏览器环境中创建专业的 PDF 文档。

  • 官方 GitHub 仓库https://github.com/bpampuch/pdfmake
  • 适用环境:Node.js、Web 浏览器
  • 主要特点:创建 PDF 文档、添加文本、表格、图片、样式设置等

2. 核心功能

2.1 基本功能

  • 文档创建:生成新的 PDF 文档
  • 文本处理:添加和格式化文本
  • 段落设置:设置段落对齐、缩进、间距等
  • 页面设置:设置页面大小、边距、方向等
  • 页眉页脚:添加和设置页眉页脚
  • 页码管理:添加页码和页码格式

2.2 高级功能

  • 样式管理:定义和应用文本样式
  • 表格创建:创建和格式化表格
  • 图片插入:添加图片到文档
  • 列表功能:创建有序和无序列表
  • 超链接:添加内部和外部超链接
  • 二维码生成:添加二维码到文档
  • 条形码生成:添加条形码到文档
  • 水印功能:添加水印到文档
  • 多列布局:创建多列布局的文档

3. 安装与设置

3.1 在 Node.js 环境中安装

npm install pdfmake

3.2 在浏览器中使用

可以通过 CDN 直接引入:

<script src="https://unpkg.com/pdfmake@latest/build/pdfmake.min.js"></script>
<script src="https://unpkg.com/pdfmake@latest/build/vfs_fonts.js"></script>

或者使用打包工具如 Webpack、Rollup 等引入。

4. 基本使用示例

4.1 创建简单文档

// 导入库(Node.js 环境)
const pdfMake = require('pdfmake/build/pdfmake');
const pdfFonts = require('pdfmake/build/vfs_fonts');
pdfMake.vfs = pdfFonts.pdfMake.vfs;

// 定义文档内容
const documentDefinition = {
  content: [
    { text: 'Hello World!', style: 'header' },
    { text: '这是使用 pdfmake 库创建的 PDF 文档。', style: 'content' }
  ],
  styles: {
    header: {
      fontSize: 24,
      bold: true,
      alignment: 'center',
      margin: [0, 0, 0, 20]
    },
    content: {
      fontSize: 12,
      alignment: 'left'
    }
  }
};

// 生成 PDF 文档(Node.js 环境)
const pdfDoc = pdfMake.createPdf(documentDefinition);
pdfDoc.write('hello-world.pdf');

4.2 在浏览器中下载文档

// 导入库(浏览器环境)
// 假设已经通过 CDN 引入了 pdfmake 库

// 定义文档内容
const documentDefinition = {
  content: [
    { text: 'Hello World!', style: 'header' },
    { text: '这是使用 pdfmake 库创建的 PDF 文档。', style: 'content' }
  ],
  styles: {
    header: {
      fontSize: 24,
      bold: true,
      alignment: 'center',
      margin: [0, 0, 0, 20]
    },
    content: {
      fontSize: 12,
      alignment: 'left'
    }
  }
};

// 生成并下载 PDF 文档
pdfMake.createPdf(documentDefinition).download('hello-world.pdf');

4.3 添加表格

const pdfMake = require('pdfmake/build/pdfmake');
const pdfFonts = require('pdfmake/build/vfs_fonts');
pdfMake.vfs = pdfFonts.pdfMake.vfs;

// 定义文档内容
const documentDefinition = {
  content: [
    { text: '产品列表', style: 'header' },
    {
      table: {
        headerRows: 1,
        widths: ['*', 'auto', 'auto'],
        body: [
          ['产品', '价格', '数量'],
          ['产品 A', '$10.00', '100'],
          ['产品 B', '$20.00', '50'],
          ['产品 C', '$30.00', '75'],
          ['总计', '', '225']
        ]
      },
      layout: 'lightHorizontalLines' // 表格布局
    }
  ],
  styles: {
    header: {
      fontSize: 18,
      bold: true,
      alignment: 'center',
      margin: [0, 0, 0, 20]
    }
  }
};

// 生成 PDF 文档
const pdfDoc = pdfMake.createPdf(documentDefinition);
pdfDoc.write('table-example.pdf');

4.4 添加图片

const pdfMake = require('pdfmake/build/pdfmake');
const pdfFonts = require('pdfmake/build/vfs_fonts');
const fs = require('fs');
pdfMake.vfs = pdfFonts.pdfMake.vfs;

// 读取图片文件并转换为 Base64
const imagePath = 'path/to/image.png';
const imageBuffer = fs.readFileSync(imagePath);
const imageBase64 = imageBuffer.toString('base64');
const imageData = `data:image/png;base64,${imageBase64}`;

// 定义文档内容
const documentDefinition = {
  content: [
    { text: '图片示例', style: 'header' },
    {
      image: imageData,
      width: 300,
      alignment: 'center'
    },
    { text: '这是一张图片', style: 'caption' }
  ],
  styles: {
    header: {
      fontSize: 18,
      bold: true,
      alignment: 'center',
      margin: [0, 0, 0, 20]
    },
    caption: {
      fontSize: 12,
      alignment: 'center',
      margin: [0, 10, 0, 0]
    }
  }
};

// 生成 PDF 文档
const pdfDoc = pdfMake.createPdf(documentDefinition);
pdfDoc.write('image-example.pdf');

5. 高级用法

5.1 使用样式

const pdfMake = require('pdfmake/build/pdfmake');
const pdfFonts = require('pdfmake/build/vfs_fonts');
pdfMake.vfs = pdfFonts.pdfMake.vfs;

// 定义文档内容
const documentDefinition = {
  content: [
    { text: '标题', style: 'h1' },
    { text: '副标题', style: 'h2' },
    { text: '正文内容', style: 'body' },
    {
      text: '强调文本',
      style: 'emphasis'
    }
  ],
  styles: {
    h1: {
      fontSize: 24,
      bold: true,
      margin: [0, 0, 0, 10]
    },
    h2: {
      fontSize: 18,
      bold: true,
      margin: [0, 0, 0, 10]
    },
    body: {
      fontSize: 12,
      margin: [0, 0, 0, 10]
    },
    emphasis: {
      fontSize: 12,
      italic: true,
      color: '#FF0000'
    }
  }
};

// 生成 PDF 文档
const pdfDoc = pdfMake.createPdf(documentDefinition);
pdfDoc.write('styles-example.pdf');

5.2 创建列表

const pdfMake = require('pdfmake/build/pdfmake');
const pdfFonts = require('pdfmake/build/vfs_fonts');
pdfMake.vfs = pdfFonts.pdfMake.vfs;

// 定义文档内容
const documentDefinition = {
  content: [
    { text: '任务列表', style: 'header' },
    {
      ol: [
        '完成项目规划',
        '实现核心功能',
        '编写测试用例',
        '部署上线'
      ]
    },
    { text: '学习计划', style: 'subHeader' },
    {
      ul: [
        '学习 JavaScript',
        '掌握 Node.js',
        '熟悉前端框架',
        '了解后端开发'
      ]
    }
  ],
  styles: {
    header: {
      fontSize: 18,
      bold: true,
      margin: [0, 0, 0, 10]
    },
    subHeader: {
      fontSize: 16,
      bold: true,
      margin: [0, 20, 0, 10]
    }
  }
};

// 生成 PDF 文档
const pdfDoc = pdfMake.createPdf(documentDefinition);
pdfDoc.write('list-example.pdf');

5.3 设置页面属性

const pdfMake = require('pdfmake/build/pdfmake');
const pdfFonts = require('pdfmake/build/vfs_fonts');
pdfMake.vfs = pdfFonts.pdfMake.vfs;

// 定义文档内容
const documentDefinition = {
  content: [
    { text: '页面设置示例', style: 'header' },
    { text: '这是一个使用自定义页面设置的文档。', style: 'content' }
  ],
  styles: {
    header: {
      fontSize: 18,
      bold: true,
      alignment: 'center',
      margin: [0, 0, 0, 20]
    },
    content: {
      fontSize: 12,
      alignment: 'left'
    }
  },
  pageSize: 'A4',
  pageOrientation: 'portrait',
  pageMargins: [40, 60, 40, 60], // 左、上、右、下
  header: {
    text: '文档页眉',
    style: 'header'
  },
  footer: {
    columns: [
      { text: '文档页脚', style: 'footer' },
      {
        text: '页码: ' + { pageNumbers: true },
        style: 'footer',
        alignment: 'right'
      }
    ]
  }
};

// 生成 PDF 文档
const pdfDoc = pdfMake.createPdf(documentDefinition);
pdfDoc.write('page-settings-example.pdf');

5.4 添加超链接

const pdfMake = require('pdfmake/build/pdfmake');
const pdfFonts = require('pdfmake/build/vfs_fonts');
pdfMake.vfs = pdfFonts.pdfMake.vfs;

// 定义文档内容
const documentDefinition = {
  content: [
    { text: '超链接示例', style: 'header' },
    {
      text: '访问 Google',
      link: 'https://www.google.com',
      style: 'link'
    },
    {
      text: '访问 GitHub',
      link: 'https://github.com',
      style: 'link'
    }
  ],
  styles: {
    header: {
      fontSize: 18,
      bold: true,
      margin: [0, 0, 0, 20]
    },
    link: {
      fontSize: 12,
      color: '#0000FF',
      decoration: 'underline',
      margin: [0, 0, 0, 10]
    }
  }
};

// 生成 PDF 文档
const pdfDoc = pdfMake.createPdf(documentDefinition);
pdfDoc.write('links-example.pdf');

6. 实际应用场景

6.1 生成报告

使用 pdfmake 库从数据库或 API 获取数据,生成包含表格、图表和格式化文本的专业报告。

6.2 自动化文档生成

根据用户输入或模板自动生成个性化文档,如合同、发票、简历等。

6.3 教育内容创建

为在线课程生成包含教程内容、练习和答案的 PDF 文档。

6.4 商业文档管理

创建和管理企业内部文档,如员工手册、政策文档、培训材料等。

6.5 票据生成

生成各种票据,如发票、收据、门票等,包含条形码或二维码。

7. 代码优化建议

7.1 模块化设计

将 PDF 生成逻辑拆分为多个模块,提高代码可维护性:

// PDF 生成器模块
class PdfGenerator {
  constructor() {
    this.pdfMake = require('pdfmake/build/pdfmake');
    const pdfFonts = require('pdfmake/build/vfs_fonts');
    this.pdfMake.vfs = pdfFonts.pdfMake.vfs;
  }

  createDocument(definition) {
    return this.pdfMake.createPdf(definition);
  }

  createReport(title, content) {
    const documentDefinition = {
      content: [
        { text: title, style: 'header' },
        ...content
      ],
      styles: {
        header: {
          fontSize: 18,
          bold: true,
          margin: [0, 0, 0, 20]
        }
      }
    };
    return this.createDocument(documentDefinition);
  }

  createTable(data, headers) {
    const body = [headers, ...data];
    return {
      table: {
        headerRows: 1,
        widths: headers.map(() => '*'),
        body: body
      }
    };
  }
}

// 使用示例
const generator = new PdfGenerator();
const report = generator.createReport('销售报告', [
  generator.createTable(
    [['产品 A', '$1000'], ['产品 B', '$2000']],
    ['产品', '销售额']
  )
]);
report.write('sales-report.pdf');

7.2 错误处理

添加适当的错误处理,提高代码健壮性:

try {
  const pdfMake = require('pdfmake/build/pdfmake');
  const pdfFonts = require('pdfmake/build/vfs_fonts');
  pdfMake.vfs = pdfFonts.pdfMake.vfs;
  
  const documentDefinition = {
    content: ['Hello World']
  };
  
  const pdfDoc = pdfMake.createPdf(documentDefinition);
  pdfDoc.write('document.pdf');
  console.log('PDF 文档创建成功!');
} catch (error) {
  console.error('生成 PDF 文档时出错:', error);
  // 处理错误
}

7.3 性能优化

对于大型 PDF 文档,使用异步操作和分批处理:

async function generateLargePdf(data, filename) {
  try {
    const pdfMake = require('pdfmake/build/pdfmake');
    const pdfFonts = require('pdfmake/build/vfs_fonts');
    pdfMake.vfs = pdfFonts.pdfMake.vfs;
    
    // 分批处理数据
    const batchSize = 100;
    const content = [];
    
    for (let i = 0; i < data.length; i += batchSize) {
      const batch = data.slice(i, i + batchSize);
      // 处理当前批次
      const batchContent = processBatch(batch);
      content.push(...batchContent);
      
      // 可选:在批次之间添加延迟,避免内存问题
      await new Promise(resolve => setTimeout(resolve, 100));
    }
    
    const documentDefinition = {
      content: content
    };
    
    const pdfDoc = pdfMake.createPdf(documentDefinition);
    pdfDoc.write(filename);
    console.log(`大型 PDF 文档创建成功:${filename}`);
  } catch (error) {
    console.error('生成 PDF 文档时出错:', error);
  }
}

function processBatch(batch) {
  // 处理批次数据
  return batch.map(item => ({ text: item }));
}

7.4 内存管理

对于大型 PDF 文档,注意内存使用:

// 避免一次性加载所有数据到内存
function generatePdfFromStream(stream, filename) {
  const pdfMake = require('pdfmake/build/pdfmake');
  const pdfFonts = require('pdfmake/build/vfs_fonts');
  pdfMake.vfs = pdfFonts.pdfMake.vfs;
  
  const content = [];
  
  // 从流中读取数据
  stream.on('data', chunk => {
    // 处理数据块
    content.push({ text: chunk.toString() });
  });
  
  stream.on('end', () => {
    const documentDefinition = {
      content: content
    };
    
    const pdfDoc = pdfMake.createPdf(documentDefinition);
    pdfDoc.write(filename);
    console.log(`PDF 文档创建成功:${filename}`);
  });
  
  stream.on('error', error => {
    console.error('读取流时出错:', error);
  });
}

8. 总结

pdfmake 是一个功能强大、灵活易用的 JavaScript 库,为开发者提供了在各种环境中生成 PDF 文档的能力。它的主要优势包括:

  • 跨平台兼容:可在 Node.js、浏览器等多种环境中使用
  • 功能丰富:支持从基本文本到复杂表格、图片的各种元素
  • 易于集成:简单的 API 设计,易于与现有项目集成
  • 高度可定制:支持自定义样式、页面设置、页眉页脚等
  • 活跃维护:持续更新和改进

通过本教程的学习,您应该已经掌握了 pdfmake 的基本用法和一些高级技巧,可以开始在实际项目中应用它来生成 PDF 文档了。

9. 参考资源

« 上一篇 exceljs 中文教程 下一篇 » html-pdf 中文教程