使用iText7和C#修改PDF:能否直接修改源文件而非生成新文件?
关于iText7直接修改源PDF文件的问题
iText7并不支持直接修改源PDF文件,核心原因有两点:
- PDF采用增量更新的结构设计,修改操作是在原文件末尾追加新内容,而非直接覆盖原有数据。如果同时以读(
PdfReader)和写(PdfWriter)模式打开同一个文件,会触发文件占用冲突,甚至直接损坏原文件。 PdfReader需要持续读取原文件的完整内容,若PdfWriter直接写入原文件,会破坏读取过程的数据完整性,引发异常或生成无效的PDF。
替代方案:实现"覆盖原文件"的效果
如果需要最终结果替换原文件,可以通过以下两种安全方式实现:
1. 内存流中转
先将原文件读取到内存流,修改完成后再写回原文件:
string pdfFileSrc = @"C:\UnsecurePDF\3161_Dec2023.pdf"; float fontSize = 8.00f; PdfFont fontTimesRoman = PdfFontFactory.CreateFont(iText.IO.Font.Constants.StandardFonts.TIMES_ROMAN); // 读取原文件到内存 byte[] fileBytes; using (var fs = new FileStream(pdfFileSrc, FileMode.Open, FileAccess.Read)) { fileBytes = new byte[fs.Length]; fs.Read(fileBytes, 0, fileBytes.Length); } // 在内存中完成PDF修改 using (var ms = new MemoryStream()) { using (var pdfDocument = new PdfDocument(new PdfReader(new MemoryStream(fileBytes)), new PdfWriter(ms))) { PdfAcroForm acroForm = PdfAcroForm.GetAcroForm(pdfDocument, false); var fields = acroForm.GetAllFormFields(); foreach (var field in fields) { try { field.Value.SetFont(fontTimesRoman); field.Value.SetFontSize(fontSize); } catch (Exception ex) { Console.WriteLine(ex.Message); } } } // 将修改后的内容写回原文件 using (var fs = new FileStream(pdfFileSrc, FileMode.Create, FileAccess.Write)) { ms.Seek(0, SeekOrigin.Begin); ms.CopyTo(fs); } }
2. 临时文件替换
先写入临时文件,修改完成后替换原文件:
string pdfFileSrc = @"C:\UnsecurePDF\3161_Dec2023.pdf"; string tempFile = Path.GetTempFileName(); float fontSize = 8.00f; PdfFont fontTimesRoman = PdfFontFactory.CreateFont(iText.IO.Font.Constants.StandardFonts.TIMES_ROMAN); try { using (var pdfDocument = new PdfDocument(new PdfReader(pdfFileSrc), new PdfWriter(tempFile))) { PdfAcroForm acroForm = PdfAcroForm.GetAcroForm(pdfDocument, false); var fields = acroForm.GetAllFormFields(); foreach (var field in fields) { try { field.Value.SetFont(fontTimesRoman); field.Value.SetFontSize(fontSize); } catch (Exception ex) { Console.WriteLine(ex.Message); } } } // 替换原文件 File.Delete(pdfFileSrc); File.Move(tempFile, pdfFileSrc); } finally { // 清理未使用的临时文件 if (File.Exists(tempFile)) { File.Delete(tempFile); } }
无论采用哪种方案,都建议先备份原文件,避免修改过程中出现异常导致数据丢失。
内容的提问来源于stack exchange,提问作者Beachdog
相关产品推荐
相关产品推荐

