试图为所有PDF页面设置边框会引发IO.Exception

时间:2018-01-08 10:13:46

标签: c# pdf itext

我有一个包含多个页面的现有pdf文件,我想为所有页面添加边框。

所以我创建了一个继承自PdfPageEventHelper的类,我重写了OnEndPage并将该类的实例分配给PdfWriter实例的PageEvent:

using iTextSharp.text;
using iTextSharp.text.pdf;

namespace My.Apps.WPF.Classes
{
    public class PdfEventHelper : PdfPageEventHelper
    {
        public override void OnEndPage(PdfWriter writer, iTextSharp.text.Document document)
        {
            // Add border to page
            PdfContentByte content = writer.DirectContent;
            iTextSharp.text.Rectangle rectangle = new iTextSharp.text.Rectangle(document.PageSize);
            rectangle.Left += document.LeftMargin;
            rectangle.Right -= document.RightMargin;
            rectangle.Top -= document.TopMargin;
            rectangle.Bottom += document.BottomMargin;
            content.SetColorStroke(BaseColor.BLACK);
            content.Rectangle(rectangle.Left, rectangle.Bottom, rectangle.Width, rectangle.Height);
            content.Stroke();
        }
    }
}

然后在主程序中我有一个方法,返回一个带有所有页面边框的新PDF(源文件pdf文档'pdfFilePath'是横向的,所以我保持新的方向):

private string PutBorderToPdfPages(string pdfFilePath)
{
    string newPdf = @"C:\Output.pdf";

    using (var reader = new PdfReader(pdfFilePath))
    {
        using (var fileStream = new FileStream(newPdf, FileMode.Create, FileAccess.Write))
        {
            iTextSharp.text.Document document = new iTextSharp.text.Document(reader.GetPageSizeWithRotation(1));
            PdfEventHelper pdfEvent = new PdfEventHelper();

            PdfWriter writer = PdfWriter.GetInstance(document, fileStream);
            writer.PageEvent = pdfEvent;

            document.Open();

            document.Close(); // here it crashes, see below in post exception thrown
            writer.Close();
        }
    }

    return newPdf;
}

在运行时,在行:

document.Close();

我得到一个IO.Exception,上面写着:

  

该文件没有页面。

在这种情况下,Pdf文档只有1页。

我做错了什么?我不想在现有的pdf文件中写任何内容,我只想创建一个与源完全相同但在其所有页面中都有边框的新PDF文件。

更新

ATTEMPT#1

我在下面做过,但是我把所有页面都换成了黑色(我不知道怎么做未填充的矩形):

private string PutBorderToPdfPages(string pdfFilePath)
{
    string newPdf = @"C:\Output.pdf";

    using (var reader = new PdfReader(pdfFilePath))
    {
        using (var fileStream = new FileStream(newPdf, FileMode.Create, FileAccess.Write))
        {
            using (var pdfStamper = new PdfStamper(reader, fileStream))
            {
                int PageCount = reader.NumberOfPages;   

                for (int p = 1; p <= PageCount; p++)
                {
                    // Add border to page                                
                    PdfContentByte cb = pdfStamper.GetOverContent(p);
                    iTextSharp.text.Rectangle rectangle = pdfReader.GetPageSizeWithRotation(p);
                    rectangle.BackgroundColor = iTextSharp.text.BaseColor.BLACK;                                
                    cb.Rectangle(rectangle);
                }                            
            }
        }
    }

    return newPdf;
}

ATTEMPT#2

在这次尝试中,我得到一个ObjectDisposedException:

  

无法访问已关闭的文件。

退出使用pdfStamper时:

private string PutBorderToPdfPages(string pdfFilePath)
{
    string newPdf = @"C:\Output.pdf";

    using (var reader = new PdfReader(pdfFilePath))
    {
        using (var fileStream = new FileStream(newPdf, FileMode.Create, FileAccess.Write))
        {
                    iTextSharp.text.Document document = new iTextSharp.text.Document(reader.GetPageSizeWithRotation(1));                        
                    PdfWriter writer = PdfWriter.GetInstance(document, fileStream);

                    document.Open();

                    using (var pdfStamper = new PdfStamper(reader, fileStream))
                    {                            
                        for (int p = 0; p < pdfStamper.Reader.NumberOfPages; p++)                            
                        {
                            // Add border to page
                            PdfContentByte content = writer.DirectContent;
                            iTextSharp.text.Rectangle rectangle = new iTextSharp.text.Rectangle(document.PageSize);
                            rectangle.Left += document.LeftMargin;
                            rectangle.Right -= document.RightMargin;
                            rectangle.Top -= document.TopMargin;
                            rectangle.Bottom += document.BottomMargin;
                            content.SetColorStroke(iTextSharp.text.BaseColor.BLACK);
                            content.Rectangle(rectangle.Left, rectangle.Bottom, rectangle.Width, rectangle.Height);
                            content.Stroke();
                        }
                        document.Close();
                        writer.Close();
                    }
        }
    }

    return newPdf;
}

3 个答案:

答案 0 :(得分:5)

你做

document.Open();

document.Close(); // here it crashes, see below in post exception thrown

即。您启动一个新文档,不添加任何内容,然后关闭它。因此,iText用The document has no pages.

响应它将是空的

因此,例外是完全正确的。

“为所有网页设置边框< ”现有的pdf文件“的正确方法是

  • PdfReader
  • 中打开文档
  • 创建PdfStamperPdfReader
  • 遍历它的页面并添加边框,
  • 并关闭PdfStamper

E.g。像这样对于源文件source和目标文件dest

using (PdfReader reader = new PdfReader(source))
using (PdfStamper stamper = new PdfStamper(reader, new FileStream(dest, FileMode.Create)))
{
    for (int pageNumber = 1; pageNumber <= reader.NumberOfPages; pageNumber++)
    {
        Rectangle cropBox = reader.GetCropBox(pageNumber);
        Rectangle rectangle = new Rectangle(cropBox);
        rectangle.Left += 20;
        rectangle.Right -= 20;
        rectangle.Top -= 20;
        rectangle.Bottom += 20;

        PdfContentByte content = stamper.GetOverContent(pageNumber);
        content.SetColorStroke(iTextSharp.text.BaseColor.BLACK);
        content.Rectangle(rectangle.Left, rectangle.Bottom, rectangle.Width, rectangle.Height);
        content.Stroke();
    }
}

答案 1 :(得分:4)

文档没有页面会引发错误,因为您创建的文档没有页面。就这么简单。

看看你的代码:

Document document = new Document(reader.GetPageSizeWithRotation(1));
PdfWriter writer = PdfWriter.GetInstance(document, fileStream);
document.Open();
document.Close();

您没有在document.Open();document.Close();

之间添加任何内容

将其更改为:

Document document = new Document(reader.GetPageSizeWithRotation(1));
PdfWriter writer = PdfWriter.GetInstance(document, fileStream);
document.Open();
document.Add(new Paragraph("Some content"));
document.Close();

错误将消失。如果您不想在文档中添加任何内容,那么...创建文档的重点是什么?

额外备注:我看到您创建的文档的页面大小取自另一个文档:reader.GetPageSizeWithRotation(1)。你的目的是什么?如果你想从另一个文件复制一个页面,你做错了!您应该使用PdfStamper代替;也就是说,如果你坚持使用旧版的iText。

真正的解决方案:升级到iText 7,您将不会遇到此问题。

答案 2 :(得分:0)

这个问题经历了一些重大变化,因此我不会更新我的初始答案(我认为这是对最初问题的正确答案),而是发布新答案以回复更新后的问题。

您正在将PdfWriter代码与PdfStamper代码混合,这是错误的。当您创建PdfStamper实例时,会自动在内部创建PdfWriter实例。

这是错误的:

using (var reader = new PdfReader(pdfFilePath))
{
    using (var fileStream = new FileStream(newPdf, FileMode.Create, FileAccess.Write))
    {
        Document document = new Document(reader.GetPageSizeWithRotation(1));                        
        PdfWriter writer = PdfWriter.GetInstance(document, fileStream);
        document.Open();
        using (var pdfStamper = new PdfStamper(reader, fileStream))
        {                            
            for (int p = 0; p < pdfStamper.Reader.NumberOfPages; p++)                            
            {
                // Add border to page
                PdfContentByte content = writer.DirectContent;
                Rectangle rectangle = new Rectangle(document.PageSize);
                rectangle.Left += document.LeftMargin;
                rectangle.Right -= document.RightMargin;
                rectangle.Top -= document.TopMargin;
                rectangle.Bottom += document.BottomMargin;
                content.SetColorStroke(iTextSharp.text.BaseColor.BLACK);
                content.Rectangle(rectangle.Left, rectangle.Bottom, rectangle.Width, rectangle.Height);
                content.Stroke();
            }
            document.Close();
            writer.Close();
        }
    }
}

请试试这个:

using (var reader = new PdfReader(pdfFilePath))
{
    using (var fileStream = new FileStream(newPdf, FileMode.Create, FileAccess.Write))
    {
        using (var pdfStamper = new PdfStamper(reader, fileStream))
        {                            
            for (int p = 1; p <= reader.NumberOfPages; p++)                            
            {
                // Add border to page
                PdfContentByte content = pdfStamper.GetOverContent(p);
                Rectangle rectangle = new Rectangle(pdfReader.GetPageSize(p));
                rectangle.Left += margin;
                rectangle.Right -= margin;
                rectangle.Top -= margin;
                rectangle.Bottom += margin;
                content.SetColorStroke(iTextSharp.text.BaseColor.BLACK);
                content.Rectangle(rectangle.Left, rectangle.Bottom, rectangle.Width, rectangle.Height);
                content.Stroke();
            }
        }
    }
}