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

基于C#与Pdftk实现PDF合并时自动补空白页的技术问询

用C#结合Pdftk实现带空白页补全的PDF合并工具修改方案

核心逻辑

要实现适配双面打印的PDF合并,核心是给每个奇数页的PDF追加空白页,确保每个子PDF的页数为偶数。流程如下:

  1. 遍历所有待合并的PDF文件,通过Pdftk获取每个文件的页数
  2. 对奇数页的PDF,将其与单页空白PDF合并成偶数页的临时文件;偶数页的PDF直接复制为临时文件
  3. 用Pdftk将所有处理后的临时文件合并为最终PDF
  4. 清理临时文件,避免残留

关键实现步骤及代码修改

1. 添加获取PDF页数的方法

通过调用Pdftk的dump_data命令解析页数:

private static int GetPdfPageCount(string pdfPath)
{
    var processStartInfo = new ProcessStartInfo
    {
        FileName = "pdftk",
        Arguments = $"\"{pdfPath}\" dump_data",
        RedirectStandardOutput = true,
        UseShellExecute = false,
        CreateNoWindow = true
    };

    using var process = Process.Start(processStartInfo);
    var output = process.StandardOutput.ReadToEnd();
    process.WaitForExit();

    var pageCountLine = output.Split(Environment.NewLine)
        .FirstOrDefault(line => line.StartsWith("NumberOfPages:"));
    
    if (pageCountLine == null)
        throw new InvalidOperationException($"无法获取PDF {pdfPath} 的页数");
    
    return int.Parse(pageCountLine.Split(':')[1].Trim());
}

2. 生成空白页PDF

你可以选择两种方式获取空白页PDF:

  • 方式一:预先准备空白PDF:创建一个单页空白PDF文件(比如blank.pdf),放在工具可访问的路径下
  • 方式二:动态生成:通过Pdftk命令生成临时空白页(适合不想依赖外部文件的场景):
private static string GenerateBlankPdf(string tempDir)
{
    var blankPdfPath = Path.Combine(tempDir, $"blank_{Guid.NewGuid()}.pdf");
    var processStartInfo = new ProcessStartInfo
    {
        FileName = "pdftk",
        Arguments = $"A=- cat A1 output \"{blankPdfPath}\"",
        UseShellExecute = false,
        CreateNoWindow = true
    };

    using var process = Process.Start(processStartInfo);
    process.WaitForExit();
    return blankPdfPath;
}

3. 修改合并流程,处理每个PDF文件

假设原代码有一个待合并文件列表inputPdfPaths和输出路径outputPdfPath,修改后的流程如下:

public static void MergePdfsForDuplexPrint(string[] inputPdfPaths, string outputPdfPath)
{
    var tempDir = Path.Combine(Path.GetTempPath(), $"pdf_merge_temp_{Guid.NewGuid()}");
    Directory.CreateDirectory(tempDir);
    var processedTempPaths = new List<string>();
    string blankPdfPath = null;

    try
    {
        // 生成或获取空白页PDF
        blankPdfPath = GenerateBlankPdf(tempDir);
        // 或者使用预先准备的文件:blankPdfPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "blank.pdf");

        foreach (var pdfPath in inputPdfPaths)
        {
            var pageCount = GetPdfPageCount(pdfPath);
            var tempPath = Path.Combine(tempDir, $"processed_{Path.GetFileName(pdfPath)}");

            if (pageCount % 2 != 0)
            {
                // 奇数页,合并原PDF和空白页
                var processStartInfo = new ProcessStartInfo
                {
                    FileName = "pdftk",
                    Arguments = $"\"{pdfPath}\" \"{blankPdfPath}\" cat output \"{tempPath}\"",
                    UseShellExecute = false,
                    CreateNoWindow = true
                };

                using var process = Process.Start(processStartInfo);
                process.WaitForExit();
            }
            else
            {
                // 偶数页,直接复制
                File.Copy(pdfPath, tempPath, true);
            }

            processedTempPaths.Add(tempPath);
        }

        // 合并所有处理后的临时PDF
        var mergeArgs = string.Join(" ", processedTempPaths.Select(p => $"\"{p}\"")) + $" cat output \"{outputPdfPath}\"";
        var mergeProcessStartInfo = new ProcessStartInfo
        {
            FileName = "pdftk",
            Arguments = mergeArgs,
            UseShellExecute = false,
            CreateNoWindow = true
        };

        using var mergeProcess = Process.Start(mergeProcessStartInfo);
        mergeProcess.WaitForExit();
    }
    finally
    {
        // 清理临时文件
        if (Directory.Exists(tempDir))
        {
            try
            {
                Directory.Delete(tempDir, true);
            }
            catch
            {
                // 忽略清理失败的情况,避免程序崩溃
            }
        }
    }
}

4. 命令行入口修改

解析命令行参数,调用上述合并方法:

static void Main(string[] args)
{
    if (args.Length < 2)
    {
        Console.WriteLine("用法:PdfMergeTool <输出路径> <输入PDF1> <输入PDF2> ...");
        return;
    }

    var outputPath = args[0];
    var inputPaths = args.Skip(1).ToArray();
    MergePdfsForDuplexPrint(inputPaths, outputPath);
    Console.WriteLine("合并完成!");
}

注意事项

  • 确保Pdftk已添加到系统环境变量,或者在代码中指定Pdftk的完整路径(比如FileName = @"C:\Program Files\Pdftk\pdftk.exe")
  • 处理大文件时,临时目录要确保有足够的磁盘空间
  • 可根据实际需求增强异常处理,比如捕获Pdftk执行失败的情况

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 04:06:26