在.NET中利用iTextSharp创立/读取PDF报告: Part I [翻译]

原稿地址:Create/Read Advance PDF Report using iTextSharp in C# .NET:
Part
I
   
By Debopam
Pal
,
27 Nov 2013

 

到PDF原文介绍了iTextSharp这几个类库,并演示了一些中坚的操作,基本属于入门等第的,可惜笔者并从未在编排后续的小说。

恰巧本人也在念书那个类库,想完结3个导出ASPX页面到PDF的机能,如笔者所说,网上找到的演示很多都以指向旧版本iTextSharp编写的,还有些驴唇马嘴,而且,许多照抄的连验证都省了,一点价值都未曾。那篇小说算是详实的入门小说,实例也都基本操作了一次达成没格外。

ps.:第3遍翻译老外的篇章,阿尔巴尼亚语水平一般,有个别地点词不达意,还望海涵,即便进出希望扶助指出。

小说内容

简介

近期自家一直在物色1个高级的工具来创立复杂的PDF报告用在C#.NET中,小编找到了iTextSharp.主要的标题是iTextSharp.缺少文书档案。好呢,有微量的C#代码例子,不过那三个对初学者的话是不够的还要那一个示例代码都以创设在iTextSharp的旧版本上,在新型版本上有繁多扭转。所以,对初学者的话转变旧版本到新本子比较艰巨。此外,作者觉着1旦作者写一篇关于iTextSharp的小说,它能扶助自个儿还要也能作为日后的参照,笔者将为每一个功用点书写示例。老实说,在那篇文章,作者编写的具备示例,你都能在《iText
in Action, Second
Edition
》那本书的首先节找到,那本书是针对Java开辟者编写的。作者就要自个儿的稿子中解释[从java到c#]那本书余下章节的兼具的示例.所以,倘若有人对那些库(iTextSharp)感兴趣,那里将是1个好的开头。

想掌握有关(iTextSharp)的更加多细节,能够通过他们的官网了解

要求

  • 编写翻译这几个类库,你要求一个C#二〇〇九(vs2010)编写翻译器恐怕更加高版本,Visual
    Studio 二零零六 or Visual C# 2008 Express Edition
  • 那些库代码运行在:
    • .NET 2.0
    • .NET 3.0
    • .NET 3.5
    • .NET 4.0
    • .NET 4.0 Client Profile
    • .NET 4.5
    • .NET 4.5 Client Profile

安装

或者
你可以从底下那一个SourceForge的链接下载DLL,然后参照下边步骤:

  • 增进引用BlahBlah(步骤如下,翻译掠过). Just see the image below:
    图片 1
  • 您须要引进到C#文本中的命名空间:
    • iTextSharp.text
    • iTextSharp.text.pdf

高速入门

陆步创立二个PDF文档:

  • Step 一: 创建一个 System.IO.FileStream 对象:

    FileStream fs = new FileStream(“Chapter1_Example1.pdf”, FileMode.Create, FileAccess.Write, FileShare.None);

  • Step 二: 创设二个 iTextSharp.text.Document 对象:

    Document doc = new Document();

  • Step 叁: 创设3个 iTextSharp.text.pdf.PdfWriter 对象:
    它助长把Document书写到特定的FileStream:

    PdfWriter writer = PdfWriter.GetInstance(doc, fs);

  • Step 4: 打开 Document:

    doc.Open();

  • Step 5: 创制1个 iTextSharp.text.Paragraph 对象并增多到Document里:

    doc.Add(new Paragraph(“Hello World”));

  • Step 6: 关闭 Document:

    doc.Close();

关系PDF文书档案的页面大小:

创设1个一定大小的页面,大家须要创立1个iTextSharp.text.Rectangle
对象同时传递三个页面大小的参数到它的构造函数里面,上面是概念页面大小的点子:

  • 首先种概念2个版面大小的章程:
    因此定义像素大概英寸定义3个页面尺寸。注意:在iTextSharp里头页面大小的单位是‘point。72point=壹英寸。借使大家须要二个开间=二英寸&中度=拾英寸的PDF文件,那么我们须要14四pt&72pt,让大家看下该如何做:

Rectangle rec = new Rectangle(144, 720);
  • 其次种概念版面大小的艺术:
    运用内建的 iTextSharp.text.PageSize 类定义:

    Rectangle rec2 = new Rectangle(PageSize.A4);
    

    上边是内建的版面大小。. 完整的页面大小表达链接 Documentation of
    Page
    Size
    :

    • _11X17
    • A0
    • A1
    • A10
    • A2
    • A3
    • A4
    • A4_LANDSCAPE
    • A5
    • A6
    • A7
    • A8
    • A9
    • ARCH_A
    • ARCH_B
    • ARCH_C
    • ARCH_D
    • ARCH_E
    • B0
    • B1
    • B10
    • B2
    • B3
    • B4
    • B5
    • B6
    • B7
    • B8
    • B9
    • CROWN_OCTAVO
    • CROWN_QUARTO
    • DEMY_OCTAVO
    • DEMY_QUARTO
    • EXECUTIVE
    • FLSA
    • FLSE
    • HALFLETTER
    • ID_1
    • ID_2
    • ID_3
    • LARGE_CROWN_OCTAVO
    • LARGE_CROWN_QUARTO
    • LEDGER
    • LEGAL
    • LEGAL_LANDSCAPE
    • LETTER
    • LETTER_LANDSCAPE
    • NOTE
    • PENGUIN_LARGE_PAPERBACK
    • PENGUIN_SMALL_PAPERBACK
    • POSTCARD
    • ROYAL_OCTAVO
    • ROYAL_QUARTO
    • SMALL_PAPERBACK
    • TABLOID
  • 其两种概念版面大小的主意:
    反转文书档案的莫斯中国科学技术大学学成为宽度&反之亦然:

    Rectangle rec3 = new Rectangle(PageSize.A4.Rotate());
    

近期,把刚刚的这么些 iTextSharp.text.Rectangle 对象
(任意1个)也正是地点的 ‘rec’,恐怕 ‘rec2’要么
‘rec三’参预iTextSharp.text.Document‘s 的构造函数中:

Document doc = new Document(rec);

安装PDF文档背景象:

有几种方法来安装背景象:

  • 率先种艺术:
    供给采用对象 iTextSharp.text.BaseColor. 实例化BaseColor
    接纳System.Drawing.Color
    (.NET)对象大概你也足以用传递RAV4GB值的款型来定义:

    rec.BackgroundColor = new BaseColor(System.Drawing.Color.WhiteSmoke);
    
  • 其次种办法:
    急需利用对象 iTextSharp.text.pdf.CMYKColor. CMYKColor 通过传递
    CMYK 值的形式来布局:

    rec2.BackgroundColor = new CMYKColor(25, 90, 25, 0);
    

设置PDF文档边距:

页边距可以像设置版面大小同样来定义
加入大家设置如下的页边距:

  • Left : 0.5 inch
  • Right : 1 inch
  • Top : 1.5 inch
  • Bottom : 2.5 inch

之所以大家必要各自设置页面包车型地铁 Left, Right, Top, Bottom
页边距使用point单位,因为大家知晓 iTextSharp
中是选择point作为单位的,并且 7二 points = 一 inch.

  • Left : 36pt => 0.5 inch
  • Right : 72pt => 1 inch
  • Top : 108pt => 1.5 inch
  • Bottom : 180pt => 2.5 inch

兑现如下:

Document doc = new Document(PageSize.A4, 36, 72, 108, 180);

设置PDF文书档案文字对齐方式:

AlignmentiTextSharp.text.Paragraph目的的属性. iTextSharp
提供了各个对齐情势. 可以由此iTextSharp.text.Element
类设置对其.以下是iTextSharp提供的对齐格局:

  • ALIGN_BASELINE[^]
  • ALIGN_BOTTOM[^]
  • ALIGN_CENTER[^]
  • ALIGN_JUSTIFIED[^]
  • ALIGN_JUSTIFIED_ALL[^]
  • ALIGN_LEFT[^]
  • ALIGN_MIDDLE[^]
  • ALIGN_RIGHT[^]
  • ALIGN_TOP[^]
  • ALIGN_UNDEFINED[^]

咱俩早就知晓在 iTextSharp.text.Document
的构造函数中必要iTextSharp.text.Paragraph
对象,所以在开创Paragraph对象今后我们得以设置它的对齐方式,大家能够在Document制程把Prargraph传递进去.

完毕如下:

Paragraph para = new Paragraph("Hello World Hello World Hello World Hello World Hello World Hello World Hello World Hello World Hello World Hello World Hello World");
// Setting paragraph's text alignment using iTextSharp.text.Element class
para.Alignment = Element.ALIGN_JUSTIFIED;
// Adding this 'para' to the Document object
doc.Add(para);

安装PDF文书档案的元消息或性质:

上面那个PDF文书档案的元音讯你可以经过iTextSharp.text.Document创办的对象doc(上文的doc)里面包车型客车格局来设置:

  • Author
    Name[^)]
  • Creation
    Date[^)]
  • Creator
    Name[^)]
  • Header Name &
    Content[^)]
  • Keywords[^)]
  • Langugae[^)]
  • Producer[^)]
  • Subject[^)]
  • Title[^)]

上面是她们的片段完结:

// Setting Document properties e.g.
// 1. Title
// 2. Subject
// 3. Keywords
// 4. Creator
// 5. Author
// 6. Header
doc.AddTitle("Hello World example");
doc.AddSubject("This is an Example 4 of Chapter 1 of Book 'iText in Action'");
doc.AddKeywords("Metadata, iTextSharp 5.4.4, Chapter 1, Tutorial");
doc.AddCreator("iTextSharp 5.4.4");
doc.AddAuthor("Debopam Pal");
doc.AddHeader("Nothing", "No Header");

方今,打开一个PDF文书档案后,右键->属性,你会看到刚才设置的新闻:
图片 2

成立多页文书档案:

我们能够通过iTextSharp.text.DocumentNewPage()方法创造新页面,大家来创设伍个PDF文书档案(页面)
:

for (int i = 1; i <= 5; i++)
{
    doc.NewPage();
    doc.Add(new Paragraph(string.Format("This is a page {0}", i)));
}

从已有文书档案创造新的PDF文书档案:

大家能够运用iTextSharp.text.pdf.PdfReader指标读取一个PDF文书档案,然后选用
iTextSharp.text.pdf.PdfStamper对象来把它写到另三个PDF文书档案。完毕如下:

string originalFile = "Original.pdf";
string copyOfOriginal = "Copy.pdf";
using (FileStream fs = new FileStream(originalFile, FileMode.Create, FileAccess.Write, FileShare.None))
using (Document doc = new Document(PageSize.LETTER))
using (PdfWriter writer = PdfWriter.GetInstance(doc, fs))
{
    doc.Open();
    doc.Add(new Paragraph("Hi! I'm Original"));
    doc.Close();
}
PdfReader reader = new PdfReader(originalFile);
using (FileStream fs = new FileStream(copyOfOriginal, FileMode.Create, FileAccess.Write, FileShare.None))
// Creating iTextSharp.text.pdf.PdfStamper object to write
// Data from iTextSharp.text.pdf.PdfReader object to FileStream object
using (PdfStamper stamper = new PdfStamper(reader, fs)) { }

采纳Layer为PDF文书档案增添水印:

iTextSharp中,PDF文书档案创制后得以加上水印,在此间本人将使用iTextSharp.text.pdf.PdfLayer为已有些PDF文档(Original.pdf)增加水印。达成如下:

string watermarkedFile = "Watermarked.pdf";
// Creating watermark on a separate layer
// Creating iTextSharp.text.pdf.PdfReader object to read the Existing PDF Document
PdfReader reader1 = new PdfReader(originalFile);
using (FileStream fs = new FileStream(watermarkedFile, FileMode.Create, FileAccess.Write, FileShare.None))
// Creating iTextSharp.text.pdf.PdfStamper object to write Data from iTextSharp.text.pdf.PdfReader object to FileStream object
using (PdfStamper stamper = new PdfStamper(reader1, fs))
{
    // Getting total number of pages of the Existing Document
    int pageCount = reader1.NumberOfPages;

    // Create New Layer for Watermark
    PdfLayer layer = new PdfLayer("WatermarkLayer", stamper.Writer);
    // Loop through each Page
    for (int i = 1; i <= pageCount; i++)
    {
        // Getting the Page Size
        Rectangle rect = reader1.GetPageSize(i);

        // Get the ContentByte object
        PdfContentByte cb = stamper.GetUnderContent(i);

        // Tell the cb that the next commands should be "bound" to this new layer
        cb.BeginLayer(layer);
        cb.SetFontAndSize(BaseFont.CreateFont(
          BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED), 50);

        PdfGState gState = new PdfGState();
        gState.FillOpacity = 0.25f;
        cb.SetGState(gState);

        cb.SetColorFill(BaseColor.BLACK);
        cb.BeginText();
        cb.ShowTextAligned(PdfContentByte.ALIGN_CENTER, watermarkText, rect.Width / 2, rect.Height / 2, 45f);
        cb.EndText();

        // Close the layer
        cb.EndLayer();
    }
}

福寿无疆结果如下:
图片 3

动用Removing Layer移除刚刚创制Layer水印的PDF文书档案:

Whenever we add Layer in PDF Document, then the content of the Layer
resides under OCG Group. So if I remove this Layer we can remove the
content of the Layer also e.g. here it is Watermark Text. To remove all
the Layers from PDF Document, you have to remove OCG Group completely
from the Document usingreader.Catalog.Remove(PdfName.OCPROPERTIES).
Now follow the Steps below to remove the Watermark Text from Layer:

  • Read the existing watermarked document using
    iTextSharp.text.pdf.PdfReader‘s object
  • Taking each Page in the iTextSharp.text.pdf.PdfDictionary‘s object
    using GetPageN(int pageNumber) method of
    iTextSharp.text.pdf.PdfReader‘s object.
  • Taking the Content of the Page in the
    iTextSharp.text.pdf.PdfArray‘s object
    usingGetAsArray(PdfName.CONTENTS) method of
    iTextSharp.text.pdf.PdfDictionary‘s object
  • Loop through this array and Get each element as
    iTextSharp.text.pdf.PRStream‘s object
    usingGetAsStream(int arrayIndex) method of
    iTextSharp.text.pdf.PdfArray‘s object
  • Convert each stream into Bytes using Static method
    GetStreamBytes(PRStream stream) ofiTextSharp.text.pdf.PdfReader
    class
  • Convert these Bytes into String using
    System.Text.Encoding.ASCII.GetString(byte[] bytes)method
  • Search for the String “/OC” and also the Watermarked Text. If
    found then remove it by giving it zero length and zero data using
    two methods: Put() & SetData() of iTextSharp.text.pdf.PRStream
    class
  • Write this modified document exists in the reader to a new
    document usingiTextSharp.text.pdf.PdfStamper‘s object

Lets Implement it:

// Removing the layer created above
// 1. First we bind a reader to the watermarked file
// 2. Then strip out a branch of things
// 3. Finally use a simple stamper to write out the edited reader
PdfReader reader2 = new PdfReader(watermarkedFile);

// NOTE: This will destroy all layers in the Document, only use if you don't have any addtional layers
// Remove the OCG group completely from the Document: reader2.Catalog.Remove(PdfName.OCPROPERTIES);

// Clean up the reader, optional
reader2.RemoveUnusedObjects();

// Placeholder variables
PRStream stream;
string content;
PdfDictionary page;
PdfArray contentArray;

// Get the number of pages
int pageCount2 = reader2.NumberOfPages;

// Loop through each page
for (int i = 1; i <= pageCount2; i++)
{
    // Get the page
    page = reader2.GetPageN(i);

    // Get the raw content
    contentArray = page.GetAsArray(PdfName.CONTENTS);

    if (contentArray != null)
    {
        // Loop through content
        for (int j = 0; j < contentArray.Size; j++)
        {
            stream = (PRStream)contentArray.GetAsStream(j);

            // Convert to a String, NOTE: you might need a different encoding here
            content = System.Text.Encoding.ASCII.GetString(PdfReader.GetStreamBytes(stream));

            //Look for the OCG token in the stream as well as our watermarked text
            if (content.IndexOf("/OC") >= 0 && content.IndexOf(watermarkText) >= 0)
            {
                //Remove it by giving it zero length and zero data
                stream.Put(PdfName.LENGTH, new PdfNumber(0));
                stream.SetData(new byte[0]);
            }
        }
    }
}

// Write the content out
using (FileStream fs = new FileStream(unwatermarkedFile, 
          FileMode.Create, FileAccess.Write, FileShare.None))
using (PdfStamper stamper = new PdfStamper(reader2, fs)) { }

在开立进程为每一页增加水印:

Now, we already know that, watermark cannot be add during Page creation,
it have to add after document creation. So, I’ve created a class
PDFWriterEvents which implements the interface
iTextSharp.text.pdf.IPdfPageEventand modify the event OnStartPage.
This interface contains a set of events from the Openning & to Closing
the PDF Document. The events are following:

  • public void OnOpenDocument(PdfWriter writer, Document document)
  • public void OnCloseDocument(PdfWriter writer, Document document)
  • public void OnStartPage(PdfWriter writer, Document document)
  • public void OnEndPage(PdfWriter writer, Document document)
  • public void OnParagraph(PdfWriter writer, Document document, float paragraphPosition)
  • public void OnParagraphEnd(PdfWriter writer, Document document, float paragraphPosition)
  • public void OnChapter(PdfWriter writer, Document document, float paragraphPosition, Paragraph title)
  • public void OnChapterEnd(PdfWriter writer, Document document, float paragraphPosition)
  • public void OnSection(PdfWriter writer, Document document, float paragraphPosition, int depth, Paragraph title)
  • public void OnSectionEnd(PdfWriter writer, Document document, float paragraphPosition)
  • public void OnGenericTag(PdfWriter writer, Document document, Rectangle rect, String text)

You may modify other events accroding to your needs which occured
against a particular action. Let see the which I’ve created:

// Creating Watermark inside OnStartPage Event by implementing IPdfPageEvent interface
// So that, dusring Page Creation, Watermark will be create
class PDFWriterEvents : IPdfPageEvent
{
    string watermarkText;
    float fontSize = 80f;
    float xPosition = 300f;
    float yPosition = 800f;
    float angle = 45f;

    public PDFWriterEvents(string watermarkText, float fontSize = 80f, 
       float xPosition = 300f, float yPosition = 400f, float angle = 45f)
    {
        this.watermarkText = watermarkText;
        this.xPosition = xPosition;
        this.yPosition = yPosition;
        this.angle = angle;
    }

    public void OnOpenDocument(PdfWriter writer, Document document) { }
    public void OnCloseDocument(PdfWriter writer, Document document) { }
    public void OnStartPage(PdfWriter writer, Document document)
    {
        try
        {
            PdfContentByte cb = writer.DirectContentUnder;
            BaseFont baseFont = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.EMBEDDED);
            cb.BeginText();
            cb.SetColorFill(BaseColor.LIGHT_GRAY);
            cb.SetFontAndSize(baseFont, fontSize);
            cb.ShowTextAligned(PdfContentByte.ALIGN_CENTER, watermarkText, xPosition, yPosition, angle);
            cb.EndText();
        }
        catch (DocumentException docEx)
        {
            throw docEx;
        }
    }
    public void OnEndPage(PdfWriter writer, Document document) { }
    public void OnParagraph(PdfWriter writer, Document document, float paragraphPosition) { }
    public void OnParagraphEnd(PdfWriter writer, Document document, float paragraphPosition) { }
    public void OnChapter(PdfWriter writer, Document document, float paragraphPosition, Paragraph title) { }
    public void OnChapterEnd(PdfWriter writer, Document document, float paragraphPosition) { }
    public void OnSection(PdfWriter writer, Document document, float paragraphPosition, int depth, Paragraph title) { }
    public void OnSectionEnd(PdfWriter writer, Document document, float paragraphPosition) { }
    public void OnGenericTag(PdfWriter writer, Document document, Rectangle rect, String text) { }
}

Lets see how & when you use the object of this class:

using (FileStream fs = new FileStream(
      "Watermark_During_Page_Creation.pdf", FileMode.Create, FileAccess.Write, FileShare.None))
using (Document doc = new Document(PageSize.LETTER))
using (PdfWriter writer = PdfWriter.GetInstance(doc, fs))
{
    writer.PageEvent = new PDFWriterEvents("This is a Test");
    doc.Open();
    doc.Add(new Paragraph("This is a page 1"));
    doc.Close();
}

See, OnStartPage event called during adding a new paragraph. So I
don’t need to add watermark
later图片 4

在不存盘的状态下,导出/打字与印刷/输出PDF文件到客户端:

We can create PDF File in memory by creatig System.IO.MemorySystem‘s
object. Lets see:

using (MemoryStream ms = new MemoryStream())
using(Document document = new Document(PageSize.A4, 25, 25, 30, 30))
using(PdfWriter writer = PdfWriter.GetInstance(document, ms))
{
    document.Open();
    document.Add(new Paragraph("Hello World"));
    document.Close();
    writer.Close();
    ms.Close();
    Response.ContentType = "pdf/application";
    Response.AddHeader("content-disposition", "attachment;filename=First_PDF_document.pdf");
    Response.OutputStream.Write(ms.GetBuffer(), 0, ms.GetBuffer().Length);
}

设置PDF浏览参数:

The values of the different ViewerPreferences were originally stored
in iTextSharp.text.pdf.PdfWriter class as an integer constant. You can
set the ViewerPreferences by following two ways:

  • By setting property ViewerPreferences of
    iTextSharp.text.pdf.PdfWriter class. To know all
    theViewerPreferences and its purpose, please read
    this)
    first. E.g.-

    writer.ViewerPreferences = PdfWriter.HideMenubar;
    
  • By calling method
    AddViewerPreference(PdfName key, PdfObject value)
    ofiTextSharp.text.pdf.PdfWriter‘s object. To know which value is
    appropiate for which key, read
    this)first.
    E.g.-

    writer.AddViewerPreference(PdfName.HIDEMENUBAR, new PdfBoolean(true));
    

加密PDF文档:

By SetEncryption() method of iTextSharp.text.pdf.PdfWriter‘s object,
we can encrypt a PDF document. Read full documentation of this method
here.
To know all the encryption types, click
here.
E.g.-

writer.SetEncryption(PdfWriter.STRENGTH40BITS, null, null, PdfWriter.ALLOW_COPY);

声明

Please download the source code for detail. I hope you'll understand as the source code is documented. If any doubt, just post your comment below. Thank you.

参考文献

历史

25th Nov, 2013: PART-I Release. PART-II will release soon
图片 5

许可

This article, along with any associated source code and files, is
licensed under The Code Project Open License
(CPOL)

 

相关文章