我遇到一个问题,使用ITextSharp创建一些推送到MVC浏览器应用程序的表和图像。我想我已经缩小到使用WriteRowsSelected添加表格。
这是我的代码:
PDFEngine.cs
private byte[] BuildDocument(MemoryStream documentStream, IEnumerable<CustomPdfData> documents, bool addVoid, float defaultMagnification)
{
using (var stream = new MemoryStream())
{
var finishedDocument = new Document(new Rectangle(612f, 792f));
var writer = PdfWriter.GetInstance(finishedDocument, stream);
writer.ViewerPreferences = PdfWriter.HideWindowUI;
writer.ViewerPreferences = PdfWriter.HideMenubar;
// Open the Document for writing
finishedDocument.Open();
var zoomer = PdfAction.GotoLocalPage(1, new PdfDestination(PdfDestination.XYZ, -1, -1, defaultMagnification), writer);
writer.SetOpenAction(zoomer);
foreach (var document in documents)
{
if (document.IsNewPage)
{
finishedDocument.NewPage();
}
var results = TableEngine.BuildDocument(document);
// Build Canvas for Table
//PdfContentByte canvas = writer.DirectContent;
//canvas.SetTextMatrix(50, 50);
// Add each table to the canvas at specified coordinates
for (int tableCounter = 0; tableCounter < results.ITextTables.Count; tableCounter++)
{
PdfContentByte canvas = writer.DirectContent;
canvas.SetTextMatrix(50, 50);
var xAxis = results.PdfTables[tableCounter].XPosition;
var yAxis = results.PdfTables[tableCounter].YPosition;
results.ITextTables[tableCounter].WriteSelectedRows(0, results.PdfTables[tableCounter].ColumnSize, xAxis, yAxis, writer.DirectContent);
}
}
finishedDocument.Close();
documentStream.Close();
return stream.ToArray();
}
CheckBuilder.cs
/// <summary>
/// Used to create the fake checks needed for printing to a client
/// </summary>
/// <param name="checks">Checks to push to Builder</param>
/// <returns></returns>
public byte[] GetFakeChecks(List<HandsCheck> checks)
{
var doc = BuildCheck(checks, true, true);
return CreatePdf(doc, 0.5f, false);
}
DisplayChecks.cshtml
<object id="WebBrowser1" width="615" height="790" data= "@Url.Action("GetPdfData")" type="application/pdf" />
HomeController.cs
public FileContentResult GetPdfData()
{
int numberofChecks = int.Parse(Workspace.Get<string>("numberofChecks"));
var pdfCreator = new CheckBuilder();
var checks = GetAllChecks();
var newList = new List<Check>();
for (int counter = 0; counter < numberofChecks; counter++)
{
newList.Add(checks[counter]);
}
var rawData = pdfCreator.GetFakeChecks(newList);
return File(rawData, "application/pdf");
return null;
}
奇怪的是,似乎只有在我添加 1 表时才会发生这种情况。有没有人知道每个画布是否有任何限制?有谁知道进一步调试可能导致此问题的方法?
答案 0 :(得分:2)
您在此处引入了PDF语法错误:
PdfContentByte canvas = writer.DirectContent;
canvas.SetTextMatrix(50, 50);
使用DirectContent
,您可以获取一个对象,该对象允许您将PDF语法直接写入内容流。紧接着,您将引入一个文本状态运算符。这是非法的PDF语法:
BT
(BeginText()
)和ET
(EndText
)运营商之间)。writeSelectedRows()
方法中定义了表格的位置。长话短说:删除canvas.SetTextMatrix(50, 50);
,您的PDF中至少会出现一个语法错误。
我刚检查了iText代码库,通常你的代码应该抛出“不平衡的文本状态”异常。如果没有,则“完整性检查”不再起作用,或者您使用的是过时版本的iTextSharp。
<强>更新强>
评论1:
ISO-32000-1将文本状态定义为图形状态的子集。在图形状态中,您可以更改线宽,笔触颜色,填充颜色,所有图形对象的“当前变换矩阵”等...您可以绘制线条,形状,...图形状态,但没有文字。
文本状态是为文本保留的:您可以更改文本矩阵,定义前导,字体......以及“显示”文本。在BT和ET块之外使用文本状态运算符是非法的;例如:在图形状态下更改文本矩阵只是没有意义,因为BT / ET序列之外没有文本。嵌套BT和ET对象也是违法的。
评论2:
就个人而言,我使用Adobe Acrobat(Preflight功能)来检查损坏的PDF的语法。这是最简单的方法,但这并不意味着它很容易。虽然我非常了解ISO-32000-1,但即使我并不总是理解错误信息。
有时Acrobat无法打开PDF文件,错误是“未知”,或者Acrobat“无法分析PDF语法”。例如,参见When stamping document - Danish characters disappear and PDF becomes invalid这是我几天前回答的一个问题。在这种情况下,我尝试使用iText RUPS,我从内部检查PDF。在最坏的情况下,您需要在纯文本编辑器中检查PDF(例如,因为即使RUPS也无法打开文件)。
评论3:
当您使用writeSelectedRows()
时,iText(夏普)会自动添加BT
和ET
运算符。如果BT
已经存在,某些版本可能会忽略BT
;如果缺少BT
,某些版本的iTextSharp在使用setTextMatrix()
时可能会添加BT
。
长话短说:iText(夏普)有时会尝试修复因编程错误而导致的问题。这些修复不是完全证明,因为iText(夏普)不能总是猜测开发人员的意图。因此,修复通常会失败。士气:应该确保不要引入PDF语法错误。