0

0

PHP 使用 FPDI 合并 PDF 文件并智能适应页面方向

花韻仙語

花韻仙語

发布时间:2025-11-05 12:18:19

|

913人浏览过

|

来源于php中文网

原创

php 使用 fpdi 合并 pdf 文件并智能适应页面方向

本文详细介绍了如何使用 PHP 的 FPDI 库合并多个 PDF 文件,并解决因页面方向(纵向/横向)不一致导致内容截断的问题。通过动态检测源 PDF 页面的尺寸和方向,我们能够为每个导入的页面创建匹配的新页面,确保合并后的文档完整无损,从而实现更智能、更专业的 PDF 处理。

在 Web 应用中,经常需要处理用户上传的 PDF 文件,例如将多个 PDF 合并成一个。然而,一个常见的挑战是源 PDF 文件可能包含不同页面方向(如纵向 A4 和横向 A4)。如果简单地将所有页面导入到固定方向的新 PDF 中,横向页面内容可能会被裁剪,导致信息丢失。本教程将指导您如何利用 FPDI 库,在合并 PDF 时智能地适应每个源页面的方向和尺寸。

准备工作

在开始之前,请确保您的 PHP 环境已安装并配置好以下库:

  1. FPDF: FPDI 依赖于 FPDF,用于生成 PDF。
  2. FPDI: 用于导入现有 PDF 页面。您可以通过 Composer 安装:
    composer require setasign/fpdf
    composer require setasign/fpdi

核心原理

解决页面方向不匹配问题的关键在于:在导入每个源 PDF 页面后,首先获取该页面的实际尺寸和方向,然后根据这些信息动态地为输出 PDF 添加一个新页面,最后将源页面内容放置到这个新页面上。这样,无论源页面是纵向还是横向,都能在新文档中得到正确的呈现。

立即学习PHP免费学习笔记(深入)”;

实现步骤

以下是合并 PDF 并适应页面方向的详细实现步骤和代码示例:

听脑AI
听脑AI

听脑AI语音,一款专注于音视频内容的工作学习助手,为用户提供便捷的音视频内容记录、整理与分析功能。

下载

1. 初始化 FPDI

首先,我们需要创建一个 FPDI 实例。FPDI 扩展了 FPDF,所以可以直接使用 FPDI 的类。

<?php

require_once('vendor/autoload.php'); // 假设您使用 Composer

// 创建 FPDI 实例
$pdf = new \setasign\Fpdi\Fpdi();

// 可选:设置默认字体和页边距等,如果需要自定义输出
// $pdf->SetAutoPageBreak(true, 10);
// $pdf->SetMargins(10, 10, 10);

2. 收集待合并的 PDF 文件

将所有需要合并的 PDF 文件路径存储在一个数组中。这些文件可以是用户上传的,也可以是服务器上预先存在的。

// 示例:待合并的 PDF 文件列表
$filesToMerge = [
    'path/to/your/portrait_document.pdf',
    'path/to/your/landscape_report.pdf',
    'path/to/another/mixed_pages.pdf',
];

// 实际应用中,这可能来自表单上传或其他逻辑
// $upload_folder = 'uploads';
// $filesToMerge = [];
// if (!empty($pdf_name)) {
//     $filesToMerge[] = $upload_folder . '/' . $pdf_name;
// }
// if (!empty($new_path) && pathinfo($new_path, PATHINFO_EXTENSION) == 'pdf') {
//     $filesToMerge[] = $new_path;
// }
// ... 更多文件

3. 遍历文件并导入页面

这是实现智能页面适应的核心部分。我们将遍历每个待合并的 PDF 文件,然后遍历该文件中的每个页面。

// 遍历所有待合并的文件
foreach ($filesToMerge as $file) {
    // 检查文件是否存在且可读
    if (!file_exists($file) || !is_readable($file)) {
        error_log("Warning: File not found or not readable: " . $file);
        continue; // 跳过当前文件,继续处理下一个
    }

    try {
        // 设置源文件,获取总页数
        $pageCount = $pdf->setSourceFile($file);

        // 遍历当前文件的每一页
        for ($pageNo = 1; $pageNo <= $pageCount; $pageNo++) {
            // 导入当前页
            $templateId = $pdf->importPage($pageNo);

            // 获取导入页面的尺寸和方向
            // getTemplateSize() 返回一个包含 'width', 'height', 'orientation' 的关联数组
            $size = $pdf->getTemplateSize($templateId);

            // 根据源页面的尺寸和方向,为输出 PDF 添加一个新页面
            // $size['orientation'] 可以是 'P' (Portrait) 或 'L' (Landscape)
            // $size 数组可以直接作为第二个参数传递,FPDF 会从中提取 width 和 height
            $pdf->AddPage($size['orientation'], $size);

            // 使用导入的模板内容填充新添加的页面
            $pdf->useTemplate($templateId);

            // 可选:在每个页面上添加自定义内容,例如页眉、页脚或水印
            // $pdf->SetFont('Helvetica', '', 10);
            // $pdf->SetTextColor(0, 0, 0);
            // $pdf->SetXY(5, 5);
            // $pdf->Write(8, '合并文档示例 - 页面 ' . $pageNo);
        }
    } catch (\Exception $e) {
        error_log("Error processing file " . $file . ": " . $e->getMessage());
        // 根据需要处理异常,例如跳过该文件或终止进程
    }
}

4. 输出合并后的 PDF

最后,将生成的 PDF 输出到浏览器、保存为文件或作为字符串返回。

// 输出 PDF 到文件
$outputFilePath = 'merged_document_with_auto_orientation.pdf';
$pdf->Output('F', $outputFilePath);
echo "PDF 合并完成并保存到: " . $outputFilePath;

// 如果需要直接输出到浏览器,请使用 'I'
// $pdf->Output('I', 'merged_document.pdf');

// 如果需要作为字符串返回,请使用 'S'
// $pdf->Output('S');

完整代码示例

<?php

require_once('vendor/autoload.php'); // 假设您使用 Composer

// 创建 FPDI 实例
$pdf = new \setasign\Fpdi\Fpdi();

// 示例:待合并的 PDF 文件列表
// 请替换为您的实际文件路径
$filesToMerge = [
    'path/to/your/portrait_document.pdf',  // 示例:纵向 A4
    'path/to/your/landscape_report.pdf',   // 示例:横向 A4
    'path/to/another/mixed_pages.pdf',     // 示例:可能包含纵向和横向页面
];

// 确保输出目录存在
$outputDir = 'output_pdfs';
if (!is_dir($outputDir)) {
    mkdir($outputDir, 0777, true);
}
$outputFilePath = $outputDir . '/merged_document_with_auto_orientation.pdf';

// 遍历所有待合并的文件
foreach ($filesToMerge as $file) {
    if (!file_exists($file) || !is_readable($file)) {
        error_log("Warning: File not found or not readable: " . $file);
        continue;
    }

    try {
        // 设置源文件,获取总页数
        $pageCount = $pdf->setSourceFile($file);

        // 遍历当前文件的每一页
        for ($pageNo = 1; $pageNo <= $pageCount; $pageNo++) {
            // 导入当前页
            $templateId = $pdf->importPage($pageNo);

            // 获取导入页面的尺寸和方向
            $size = $pdf->getTemplateSize($templateId);

            // 根据源页面的尺寸和方向,为输出 PDF 添加一个新页面
            $pdf->AddPage($size['orientation'], $size);

            // 使用导入的模板内容填充新添加的页面
            $pdf->useTemplate($templateId);

            // 可选:在每个页面上添加自定义内容
            // $pdf->SetFont('Helvetica', '', 8);
            // $pdf->SetTextColor(100, 100, 100);
            // $pdf->SetXY(5, 5);
            // $pdf->Write(8, '合并示例 - ' . basename($file) . ' - 页 ' . $pageNo);
        }
    } catch (\Exception $e) {
        error_log("Error processing file " . $file . ": " . $e->getMessage());
        // 根据需要处理异常
    }
}

// 输出 PDF 到文件
try {
    $pdf->Output('F', $outputFilePath);
    echo "PDF 合并完成并保存到: " . $outputFilePath . "\n";
} catch (\Exception $e) {
    error_log("Error outputting PDF: " . $e->getMessage());
    echo "PDF 输出失败: " . $e->getMessage() . "\n";
}

?>

注意事项与最佳实践

  • 错误处理: 在实际应用中,务必加入健壮的错误处理机制。例如,检查文件是否存在、是否是有效的 PDF 文件,以及 FPDI 操作是否成功。
  • 内存管理: 合并大量或包含复杂图形的 PDF 文件可能会消耗大量内存。对于非常大的文件,考虑分批处理或优化服务器配置。
  • FPDI 版本: 确保您使用的 FPDI 和 FPDF 版本兼容。不同版本之间可能存在 API 差异。
  • PDF 复杂性: FPDI 主要处理 PDF 的视觉内容。如果源 PDF 包含交互式表单、JavaScript 或其他高级功能,这些特性在导入后可能无法完全保留。FPDI 旨在导入页面的视觉表示。
  • 性能: 对于大量页面,setSourceFile() 和 importPage() 操作可能耗时。如果性能是关键考量,可以考虑在后台任务中执行 PDF 合并。
  • 字体嵌入: 如果在合并后的 PDF 中添加自定义文本,请确保所使用的字体已嵌入或可用,以避免字体显示问题。

总结

通过本教程介绍的方法,您可以使用 PHP 和 FPDI 库高效地合并多个 PDF 文件,并智能地适应每个源页面的方向和尺寸。这种动态适应性确保了合并后的文档内容完整无缺,无论原始 PDF 的布局如何。这对于需要处理用户上传各种格式 PDF 的 Web 应用程序来说,是一个非常实用的解决方案。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
composer是什么插件
composer是什么插件

Composer是一个PHP的依赖管理工具,它可以帮助开发者在PHP项目中管理和安装依赖的库文件。Composer通过一个中央化的存储库来管理所有的依赖库文件,这个存储库包含了各种可用的依赖库的信息和版本信息。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

162

2023.12.25

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

761

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

221

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1570

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

651

2023.11.24

java读取文件转成字符串的方法
java读取文件转成字符串的方法

Java8引入了新的文件I/O API,使用java.nio.file.Files类读取文件内容更加方便。对于较旧版本的Java,可以使用java.io.FileReader和java.io.BufferedReader来读取文件。在这些方法中,你需要将文件路径替换为你的实际文件路径,并且可能需要处理可能的IOException异常。想了解更多java的相关内容,可以阅读本专题下面的文章。

1228

2024.03.22

php中定义字符串的方式
php中定义字符串的方式

php中定义字符串的方式:单引号;双引号;heredoc语法等等。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

1205

2024.04.29

go语言字符串相关教程
go语言字符串相关教程

本专题整合了go语言字符串相关教程,阅读专题下面的文章了解更多详细内容。

193

2025.07.29

TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

26

2026.03.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PHP课程
PHP课程

共137课时 | 13.5万人学习

JavaScript ES5基础线上课程教学
JavaScript ES5基础线上课程教学

共6课时 | 11.3万人学习

PHP新手语法线上课程教学
PHP新手语法线上课程教学

共13课时 | 1.0万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号