You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Angular 9中合并图片与PDF为单个PDF并实现打印?

嗨,咱们来一步步解决你的这两个Angular 9需求吧,这俩都是日常开发里很常见的场景,我给你整理了靠谱的实现方案:

一、将多图片与PDF合并为单个PDF

我推荐使用pdf-lib这个库来实现,它对PDF文档的操作非常灵活,支持嵌入图片、合并现有PDF,而且完全基于浏览器端运行,不需要后端支持。

步骤1:安装依赖

首先在你的Angular 9项目里安装库和对应的TypeScript类型定义:

npm install pdf-lib @types/pdf-lib --save

步骤2:组件实现代码

下面是完整的组件示例,包含文件选择、合并逻辑和后续操作功能:

import { Component } from '@angular/core';
import { PDFDocument } from 'pdf-lib';
import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';

@Component({
  selector: 'app-pdf-merger',
  templateUrl: './pdf-merger.component.html',
  styleUrls: ['./pdf-merger.component.css']
})
export class PdfMergerComponent {
  selectedPdf: File | null = null;
  selectedImages: File[] = [];

  constructor(private sanitizer: DomSanitizer) {}

  // 选择要合并的基础PDF文件
  onPdfSelected(event: Event) {
    const file = (event.target as HTMLInputElement).files?.[0];
    if (file && file.type === 'application/pdf') {
      this.selectedPdf = file;
    } else {
      alert('请选择有效的PDF文件');
    }
  }

  // 选择要添加的图片文件
  onImagesSelected(event: Event) {
    const files = (event.target as HTMLInputElement).files;
    if (files) {
      this.selectedImages = Array.from(files).filter(file => 
        file.type.startsWith('image/')
      );
    }
  }

  // 核心合并逻辑,支持选择下载或打印
  async mergeAndProcessFiles(shouldPrint: boolean = false) {
    if (!this.selectedPdf || this.selectedImages.length === 0) {
      alert('请选择PDF文件和至少一张图片');
      return;
    }

    try {
      // 1. 加载现有PDF文档
      const pdfBytes = await this.selectedPdf.arrayBuffer();
      const pdfDoc = await PDFDocument.load(pdfBytes);

      // 2. 遍历图片,逐个添加到PDF末尾
      for (const imgFile of this.selectedImages) {
        const imgBytes = await imgFile.arrayBuffer();
        const img = imgFile.type === 'image/png' 
          ? await pdfDoc.embedPng(imgBytes)
          : await pdfDoc.embedJpg(imgBytes);

        // 计算图片缩放比例,适配A4页面(避免超出边界)
        const a4Width = 595.28; // PDF标准A4宽度(单位:点)
        const a4Height = 841.89; // PDF标准A4高度
        const scale = Math.min(a4Width / img.width, a4Height / img.height);
        const scaledWidth = img.width * scale;
        const scaledHeight = img.height * scale;

        // 添加新页面并绘制图片
        const newPage = pdfDoc.addPage([scaledWidth, scaledHeight]);
        newPage.drawImage(img, {
          x: 0,
          y: 0,
          width: scaledWidth,
          height: scaledHeight,
        });
      }

      // 3. 生成合并后的PDF字节数据
      const mergedPdfBytes = await pdfDoc.save();

      // 根据需求选择下载或打印
      if (shouldPrint) {
        await this.printPdf(mergedPdfBytes);
      } else {
        this.downloadPdf(mergedPdfBytes);
      }
    } catch (error) {
      console.error('合并失败:', error);
      alert('PDF合并出错,请检查文件格式后重试');
    }
  }

  // 下载合并后的PDF
  downloadPdf(pdfBytes: Uint8Array) {
    const blob = new Blob([pdfBytes], { type: 'application/pdf' });
    const url = URL.createObjectURL(blob);
    const aTag = document.createElement('a');
    aTag.href = url;
    aTag.download = 'merged-result.pdf';
    aTag.click();
    URL.revokeObjectURL(url);
  }

  // 打印合并后的PDF
  async printPdf(pdfBytes: Uint8Array) {
    const blob = new Blob([pdfBytes], { type: 'application/pdf' });
    const url = URL.createObjectURL(blob);
    const safeUrl = this.sanitizer.bypassSecurityTrustResourceUrl(url);

    // 创建隐藏iframe加载PDF,避免页面跳转
    const iframe = document.createElement('iframe');
    iframe.style.display = 'none';
    iframe.src = safeUrl as string;
    document.body.appendChild(iframe);

    // 等待PDF加载完成后触发打印
    iframe.onload = () => {
      setTimeout(() => {
        iframe.contentWindow?.print();
        document.body.removeChild(iframe);
        URL.revokeObjectURL(url);
      }, 1000); // 延迟1秒确保PDF完全加载,可根据实际情况调整
    };
  }
}

步骤3:模板代码(html)

在组件的模板里添加文件选择器和操作按钮:

<div class="pdf-merger-container">
  <div>
    <label>选择基础PDF文件:</label>
    <input type="file" accept=".pdf" (change)="onPdfSelected($event)">
  </div>
  <div>
    <label>选择要添加的图片(支持多张):</label>
    <input type="file" accept="image/png, image/jpeg" multiple (change)="onImagesSelected($event)">
  </div>
  <div class="button-group">
    <button (click)="mergeAndProcessFiles(false)" [disabled]="!selectedPdf || selectedImages.length === 0">
      合并并下载
    </button>
    <button (click)="mergeAndProcessFiles(true)" [disabled]="!selectedPdf || selectedImages.length === 0">
      合并并打印
    </button>
  </div>
</div>
二、合并后实现打印功能

上面的代码里已经内置了完整的打印逻辑,核心思路是:

  1. 将合并后的PDF字节数据转为Blob URL
  2. 通过隐藏的iframe加载PDF(避免页面跳转)
  3. 等待PDF加载完成后调用浏览器原生的print()方法

关键注意事项

  • 因为Angular的安全策略,Blob URL需要通过DomSanitizer处理成安全资源URL,否则会被框架阻止加载
  • 延迟1秒触发打印是为了确保PDF完全加载,不同浏览器的加载速度不同,可根据实际情况调整这个时间
  • 部分浏览器会默认拦截弹窗类请求,需要用户允许打印窗口弹出

如果需要更自定义的打印样式(比如添加页眉页脚、调整打印尺寸),可以考虑先把PDF转成HTML片段,用html2canvas渲染后再打印,但这种方式复杂度更高,上面的方案已经能满足大部分常规打印需求。


内容的提问来源于stack exchange,提问作者Priyank

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 17:42:56