![](/img/trans.png)
[英]Write to an existing pdf file and save it as a new file using itextsharp
[英]Write to a PDF file with fields multiple times using iTextSharp
我有一個PDF文檔,其中包含3個字段txt_FirstName
, txt_MiddleName
和txt_LastName
,我使用iTextSharp寫入。
我有一個循環,創建輸出文件,寫入它,並關閉文件。
第一次在循環中,文件寫入名字和中間名。
在循環中第二次,文件應該具有名字,中間名,並寫下姓氏。
問題:問題是,當它第二次進入循環時,將姓氏寫成名字,中間名稱消失。
目標:我想做的主要是多次寫入相同的PDF文檔
下載PDF模板: https : //www.scribd.com/document/412586469/Testing-Doc
public static string templatePath = "C:\\temp\\template.pdf";
public static string OutputPath = "C:\\Output\\";
private static void Fill_PDF()
{
string outputFile = "output.pdf";
int counter = 1;
for (int i = 0; i < 2; i++)
{
PdfStamper pdfStamper;
PdfReader reader;
reader = new PdfReader(File.ReadAllBytes(templatePath));
PdfReader.unethicalreading = true;
if (File.Exists(OutputPath + outputFile))
{
pdfStamper = new PdfStamper(reader, new FileStream(OutputPath + outputFile,
FileMode.Append, FileAccess.Write));
}
else
{
pdfStamper = new PdfStamper(reader, new FileStream(OutputPath + outputFile,
FileMode.Create));
}
AcroFields pdfFormFields = pdfStamper.AcroFields;
if (counter == 1)
{
pdfFormFields.SetField("txt_FirstName", "Scooby");
pdfFormFields.SetField("txt_MiddleName", "Dooby");
counter++;
}
else if (counter == 2)
{
pdfFormFields.SetField("txt_LastName", "Doo");
}
pdfStamper.Close();
}
}
這似乎是一個簡單的錯誤。 第一次循環時,加載空白模板並寫入第一個和中間名。 第二次循環, 再次加載空白模板 , 只寫入姓氏 ,然后保存到相同的文件名,覆蓋它。 如果,在第二次循環中,您要加載已包含第一個和中間名的文件,則必須加載第一次編寫的輸出文件 ,而不是再次加載空白模板。 或者,如果要再次加載空白模板,在if (counter == 2)
子句中,您將不得不編寫所有3個名稱,而不僅僅是姓氏。
我復制了你的bug,讓它運行起來。 這是我描述的第一個解決方案的代碼(對代碼的小修改):
public static string templatePath = "C:\\temp\\template.pdf";
public static string OutputPath = "C:\\temp\\output\\";
private static void Fill_PDF()
{
string outputFile = "output.pdf";
int counter = 1;
for (int i = 0; i < 2; i++)
{
PdfStamper pdfStamper;
PdfReader reader = null;
/********** here's the changed part */
if (counter == 1)
{
reader = new PdfReader(File.ReadAllBytes(templatePath));
} else if (counter == 2)
{
reader = new PdfReader(File.ReadAllBytes(OutputPath + outputFile));
}
/************ end changed part */
PdfReader.unethicalreading = true;
if (File.Exists(OutputPath + outputFile))
{
pdfStamper = new PdfStamper(reader, new FileStream(OutputPath + outputFile,
FileMode.Append, FileAccess.Write));
}
else
{
pdfStamper = new PdfStamper(reader, new FileStream(OutputPath + outputFile,
FileMode.Create));
}
AcroFields pdfFormFields = pdfStamper.AcroFields;
if (counter == 1)
{
pdfFormFields.SetField("txt_FirstName", "Scooby");
pdfFormFields.SetField("txt_MiddleName", "Dooby");
counter++;
}
else if (counter == 2)
{
pdfFormFields.SetField("txt_LastName", "Doo");
}
pdfStamper.Close();
}
}
代碼有兩個主要問題。 @Nick在他的回答中已經指出了第一個:如果在第二遍中你想要編輯包含第一遍的變化的文檔版本,你必須將第一遍的輸出文檔作為第二遍的輸入,不是原始模板。 他還提出了修復此問題的代碼。
第二個問題位於:
if (File.Exists(OutputPath + outputFile))
{
pdfStamper = new PdfStamper(reader, new FileStream(OutputPath + outputFile,
FileMode.Append, FileAccess.Write));
}
else
{
pdfStamper = new PdfStamper(reader, new FileStream(OutputPath + outputFile,
FileMode.Create));
}
如果輸出文件已存在, PdfStamper
的輸出附加到其中 。 這是錯的! PdfStamper
的輸出已包含原始PDF(來自PdfReader
)的內容,只要它們沒有被更改。 因此,您的代碼有效地生成第一遍的完整輸出PDF和第二遍的完整輸出PDF的串聯。
PDF是一種二進制格式,其中的連接文件不會生成有效的PDF文件。 因此,加載最終結果的PDF查看器會嘗試修復此雙PDF,假設它是單個PDF。 結果可能或可能不是您想要的結果。
要解決第二個問題,只需將if{...}else{...}
替換為else
分支的內容:
pdfStamper = new PdfStamper(reader, new FileStream(OutputPath + outputFile,
FileMode.Create));
( FileMode.Create
定義為
指定操作系統應創建新文件。 如果該文件已存在,則將被覆蓋。 這需要
Write
權限。FileMode.Create
等同於請求如果文件不存在,則使用CreateNew
; 否則,請使用Truncate
。 如果文件已存在但是是隱藏文件,則拋出UnauthorizedAccessException
異常。
因此,如果已有文件,它也會執行所需的操作。)
您可以通過運行它幾次來識別代碼中包含Append
的問題,並觀察輸出文件的增長和增長超出需要。 此外,如果您在Adobe Reader中打開該文件並再次關閉,Adobe Reader會保存更改; 變化是修復工作。
您可能聽說過改變被附加到原始PDF PDF文件的增量更新 。 但這與僅僅連接不同,結果中的修訂是特殊關聯的,並且偏移總是從第一次修訂的開始計算,而不是從當前修訂的開始計算。 此外,增量更新應僅包含已更改的對象。
iText包含一個帶有4個參數的PdfStamper
構造函數,包括最后一個布爾參數append
。 使用該構造函數並將append
設置為true
會使iText創建增量更新。 但即使在這里你也不要使用FileMode.Append
......
問題是再次使用模板文件進行第二次迭代。
第一次迭代:按預期正常工作!
第二次迭代:您正在讀取相同的文件並僅寫入姓氏。 最后,將替換在第一次迭代中創建的輸出文件。
修復:在知道輸出文件是否存在於該位置后,選擇要讀取的文件源,如下所示。 這應該可以解決問題。 親自檢查,它的工作原理!
if (File.Exists(OutputPath + outputFile))
{
reader = new PdfReader(File.ReadAllBytes(OutputPath + outputFile));
pdfStamper = new PdfStamper(reader, new FileStream(OutputPath + outputFile,
FileMode.Append, FileAccess.Write));
}
else
{
reader = new PdfReader(File.ReadAllBytes(templatePath));
pdfStamper = new PdfStamper(reader, new FileStream(OutputPath + outputFile,
FileMode.Create));
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.