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

C# iText生成/修改PDF:坐标转换与内存流操作技术问询

嘿,我看你在用iTextSharp处理PDF操作,正好能帮你解决这几个问题,咱们一步步来:

1. 厘米与磅的坐标转换

PDF的默认单位是磅(Point),咱们常用的厘米和磅的转换关系很清晰:

  • 1英寸 = 72磅
  • 1厘米 = 2.54英寸

我帮你写两个静态工具方法,方便随时调用转换:

// 厘米转磅
public static float CmToPoints(float cm)
{
    return cm * 72 / 2.54f;
}

// 磅转厘米(需要反向转换时用)
public static float PointsToCm(float points)
{
    return points * 2.54f / 72;
}

举个实际例子:

  • 3厘米转磅:CmToPoints(3) ≈ 85.04磅
  • 10厘米转磅:CmToPoints(10) ≈ 283.47磅

另外要注意一个容易踩的坑:PDF的坐标原点在页面的左下角,所以“距顶部10厘米”的位置,得用页面高度减去转换后的磅值,比如A4页面高度是841.89磅,那对应的y坐标就是 841.89 - CmToPoints(10)。

2. 创建新PDF或加载已有PDF修改

创建新PDF

你原代码里的SetSimpleColumn参数顺序有点问题,这个方法的参数是x1(左下角x)、y1(左下角y)、x2(右上角x)、y2(右上角y),我已经在下面的完整代码里修正了这部分,还结合坐标转换方法帮你设置了指定位置的文本。

加载已有PDF修改

要修改已有PDF,咱们得用PdfReader读取原文件,再用PdfStamper来添加内容,这样既能保留原PDF的所有内容,又能在指定位置添加新文本。

3. 用内存流修改PDF并覆盖原文件

直接同时读写同一个文件会报错,所以咱们用内存流中转:

  1. 先把原文件读入内存流
  2. 基于内存流创建PdfReader进行修改
  3. 将修改后的内容写入新的内存流
  4. 最后把新内存流的内容覆盖回原文件

下面是整合了所有需求的完整代码,每一步都加了注释:

using System;
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;

namespace CreateChangePdf
{
    class Program
    {
        static void Main(string[] args)
        {
            string fileName = @"c:\data\pdftest.pdf";
            string textToAdd = @"New text";
            
            // 示例:文本距左侧3厘米、距顶部10厘米
            float leftDistanceCm = 3;
            float topDistanceCm = 10;
            
            if (File.Exists(fileName))
            {
                // 用内存流修改已有PDF并覆盖原文件
                ModifyPdfWithMemoryStream(fileName, textToAdd, leftDistanceCm, topDistanceCm);
            }
            else
            {
                // 创建新PDF并添加指定位置的文本
                CreateNewPdf(fileName, textToAdd, leftDistanceCm, topDistanceCm);
            }
        }

        // 厘米转磅的工具方法
        public static float CmToPoints(float cm)
        {
            return cm * 72 / 2.54f;
        }

        // 创建新PDF的方法
        private static void CreateNewPdf(string filePath, string text, float leftCm, float topCm)
        {
            using (var outputStream = new FileStream(filePath, FileMode.Create))
            {
                var document = new Document(PageSize.A4);
                var writer = PdfWriter.GetInstance(document, outputStream);
                
                document.Open();
                var contentByte = writer.DirectContent;
                var columnText = new ColumnText(contentByte);
                
                // 获取A4页面的高度(也可以用document.PageSize.Height)
                float pageHeight = PageSize.A4.Height;
                // 计算坐标:x是左侧距离转磅,y是页面高度减去顶部距离转磅(因为原点在左下角)
                float xPos = CmToPoints(leftCm);
                float yPos = pageHeight - CmToPoints(topCm);
                
                // 设置文本显示的区域:从(xPos,yPos)开始,宽度200磅,行高15磅
                columnText.SetSimpleColumn(
                    new Phrase(text, FontFactory.GetFont(FontFactory.COURIER, 12, Font.NORMAL)),
                    xPos, yPos, xPos + 200, yPos + 15,
                    0, Element.ALIGN_LEFT
                );
                columnText.Go();
                
                document.Close();
            }
        }

        // 用内存流修改PDF并覆盖原文件的方法
        private static void ModifyPdfWithMemoryStream(string filePath, string text, float leftCm, float topCm)
        {
            byte[] originalPdfBytes;
            
            // 第一步:把原文件读入内存
            using (var originalFileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
            using (var memoryStream = new MemoryStream())
            {
                originalFileStream.CopyTo(memoryStream);
                originalPdfBytes = memoryStream.ToArray();
            }

            // 第二步:修改PDF内容到新的内存流
            using (var modifiedMemoryStream = new MemoryStream())
            {
                var pdfReader = new PdfReader(originalPdfBytes);
                var pdfStamper = new PdfStamper(pdfReader, modifiedMemoryStream);
                
                // 获取第一页的内容层(GetOverContent是在原内容上方添加,GetUnderContent是下方)
                var contentByte = pdfStamper.GetOverContent(1);
                var columnText = new ColumnText(contentByte);
                
                float pageHeight = pdfReader.GetPageSize(1).Height;
                float xPos = CmToPoints(leftCm);
                float yPos = pageHeight - CmToPoints(topCm);
                
                columnText.SetSimpleColumn(
                    new Phrase(text, FontFactory.GetFont(FontFactory.COURIER, 12, Font.NORMAL)),
                    xPos, yPos, xPos + 200, yPos + 15,
                    0, Element.ALIGN_LEFT
                );
                columnText.Go();
                
                // 关闭资源
                pdfStamper.Close();
                pdfReader.Close();
                
                // 第三步:把修改后的内容覆盖回原文件
                using (var outputFileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write))
                {
                    modifiedMemoryStream.Seek(0, SeekOrigin.Begin);
                    modifiedMemoryStream.CopyTo(outputFileStream);
                }
            }
        }
    }
}

额外提醒

  • 确保你已经通过NuGet安装了iTextSharp包(可以在NuGet包管理器里搜索iTextSharp并安装)
  • 如果需要修改PDF的所有页面,可以循环pdfReader.NumberOfPages,对每一页执行添加文本的逻辑
  • 如果要真正“覆盖”原有内容(而不是添加在上方),需要先清除对应区域的内容,这个操作比较复杂,一般用GetOverContent添加新内容就能满足需求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:29:16