2013-08-20 318 views
0

我有一个问题,使用ITextSharp创建一些表和图像推送到MVC浏览器应用程序。我想我已经缩小到使用WriteRowsSelected添加表格了。获取“此页面存在错误,Acrobat可能无法正确显示页面。”使用ITextSharp WriteSelectedRows

这里是我的代码:

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; 
    } 

奇怪的是,它似乎当我添加超过表才会发生。有谁知道每个画布是否有限制?有谁知道有什么方法可以进一步调试可能导致此问题的原因?

+0

除了传递'Stream'对象外,没有什么会跳出来。我从来没有找到一个很好的理由来做到这一点,但看到很多理由不去做。你可以尝试重构只使用内部的'MemoryStream',并使用'MS.ToArray()'返回一个原始字节数组。这也会给你带来好处,不必担心记住要关闭方法以外的流,还要调用错误的流方法,比如'GetBuffer'。 –

+0

感谢@Chris的回复。我更新了上面的代码以包含推荐的重构。我想我做了你所要求的,但我仍然得到了错误。奇怪的是,PDF总是显示正确。我还包括HTML和控制器代码。此外,它似乎如果我甚至添加第二个表,它会引发相同的错误。是否可能需要为多个WriteSelectedRows执行操作? – gcoleman0828

+0

此外,如果我在每个WriteRowsSelected上添加Newpage调用,它没有问题,显然这不是所需的效果,但我认为这可能有助于解决这个奇怪的问题 – gcoleman0828

回答

2

你在这里引入一个PDF语法错误:

PdfContentByte canvas = writer.DirectContent; 
canvas.SetTextMatrix(50, 50); 

随着DirectContent,你抢的对象,使您可以直接输出PDF语法内容流。紧接着,你介绍一个文本状态操作符。这是非法的PDF语法:

  1. 文本状态运算符只在文本对象内有效;即:BTBeginText())和ETEndText)运营商)之间。
  2. 为什么你需要设置文本矩阵?该行没有意义,因为您正在使用writeSelectedRows()方法定义表的位置。

长话短说:删除canvas.SetTextMatrix(50, 50);并且您的PDF中至少会有一处语法错误。

我刚刚检查了iText代码库,通常你的代码应该抛出一个“不平衡文本状态”异常。如果没有,那么“完整性检查”不再起作用,或者您正在使用过时的iTextSharp版本。

更新

注释1:

ISO-32000-1定义为图形状态的子集中的文本的状态。在图形状态中,您可以更改线宽,笔触颜色,填充颜色,所有图形对象的“当前转换矩阵”等...您可以在图形状态中绘制线条,形状...,但不可以文本。

文本状态保留为文本:您更改文本矩阵,定义领导,字体,...和你'显示'文本。在BT和ET块外使用文本状态操作符是非法的;例如:只改变图形状态下的文本矩阵没有意义,因为BT/ET序列之外没有文本。嵌套BT和ET对象也是非法的。

注释2:

就个人而言,我使用Adobe Acrobat(预检功能)来检查一个破碎的PDF的语法。这是最简单的方式,但这并不意味着它很容易。尽管我很了解ISO-32000-1,但即使我并不总是了解错误信息。

有时Acrobat无法打开PDF文件,错误为'未知',或者Acrobat'无法分析PDF语法'。例如,请参阅When stamping document - Danish characters disappear and PDF becomes invalid这是几天前我回答的问题。在这种情况下,我尝试使用iText RUPS,并从内部检查PDF。在最糟糕的情况下,您需要在纯文本编辑器中检查PDF(例如,因为即使RUPS也无法打开文件)。

点评三:

当您使用writeSelectedRows(),iText的(夏普)会自动添加一个BTET运营商。如果BT已经存在,某些版本可能会省略BT;如果缺少BT,某些版本的iTextSharp可能会在使用setTextMatrix()时添加BT

长话短说:iText(Sharp)有时会尝试修复由于编程错误而导致的问题。这些修复并不完全证明,因为iText(夏普)不能总是猜测开发人员的意图。因此,修复通常会失败。士气:应该确保不要引入PDF语法错误。

+0

老兄你摇滚..这似乎已经修复了它......我试图按照他们的API指南中的一个例子,显然我混合了一些东西。我有两个问题。 1.)你能解释一下为什么SetTextMatrix是非法语法吗?仅仅是因为它不在英国电信和ET内部,还是因为它更多?我是新来的PDF需求世界。 – gcoleman0828

+0

第二个问题是,是否有任何工具或技巧来确定实际的语法错误是不是很抽象/模糊?如果有更多信息,我可能会更快地到达某个地方。 – gcoleman0828

+0

还有一件事...你为什么认为第一个表格被添加,随后的所有表格都会导致错误? – gcoleman0828