以.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这个类库,并演示了有些中心的操作,基本属于入门级别之,可惜作者并没当编制后续的稿子。

恰好自己也当念是类库,想实现一个导出ASPX页面及PDF的职能,如作者所说,网上找到的言传身教好多都是针对性初本子iTextSharp编写的,还发生几驴唇不对马嘴,而且,很多录的连验证都看了,一点值还没有。这首稿子算详实的入门文章,实例也还基本操作了一样总体实现无问题。

ps.:第一不善翻译老外的稿子,英语水平一般,有些地方词不浅,还往海涵,如果进出希望帮助指出。

文章内容

  • 简介
  • 要求
  • 安步骤
  • 6步创建PDF文档 
  • 关联PDF文档的页面大小 
  • 安装PDF文档背景色
  • 安装PDF文档边距
  • 设置PDF文档文字对齐方式
  • 安PDF文档的首家信息还是性质
  • 始建多页文档
  • 自曾经发生文档创建新的PDF文档
  • 以Layer为PDF文档添加水印
  • 使Removing
    Layer移除刚刚创建Layer水印的PDF文档
  • 每当开立过程也各个一样页上加水印
  • E在匪存盘的动静下,导出/打印/输出PDF文件及客户端
    下面内容是在更新版本后添加的:
  • 安装PDF浏览参数
  • 加密PDF文档
  • 声明
  • 参考文献
  • 历史

简介

近日自家直接当物色一个高档的家伙来创造复杂的PDF报告用在C#.NET中,我找到了iTextSharp.主要的题材是iTextSharp.缺乏文档。好吧,有少量底C#代码例子,但是那些对初学者的话是不够的还要这些示例代码都是树立以iTextSharp的原来本子及,在风行版本及有广大转移。所以,对初学者的话转换旧本子及新本子比较艰难。此外,我当要自己写一首关于iTextSharp的文章,它能辅助我又为会作下的参照,我将为每一个职能点书示例。老实说,在这篇稿子,我修的有示例,你还能够以《iText
in Action, Second
Edition》这仍开的第一节约找到,这本书是针对Java开发者编写的。我拿以我之稿子中解释[从java到c#]即按照开余生节的备的示例.所以,如果有人对之库房(iTextSharp)感兴趣,这里以凡一个好的开始。

思念知道有关(iTextSharp)的更多细节,可以透过她们的官方网站了解

要求

  • 编译这个类库,你需要一个C#2008(vs2008)编译器或者再次胜版本,Visual
    Studio 2008 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

安装

  • 你待安装 NuGet
    package

或者
你得起下这SourceForge的链接下载DLL,然后参照下步骤:

  • 增长引用BlahBlah(步骤如下,翻译掠过). Just see the image below:
    图片 1
  • 乃待引入到C#文本被的命名空间:
    • iTextSharp.text
    • iTextSharp.text.pdf

高效入门

6步创建一个PDF文档:

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

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

  • Step 2: 创建一个 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: 创建一个 iTextSharp.text.Paragraph 对象并补充加至Document里:

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

  • Step 6: 关闭 Document:

    doc.Close();

干PDF文档的页面大小:

始建一个一定大小的页面,我们需要创造一个iTextSharp.text.Rectangle
对象又传递一个页面大小的参数到它们的构造函数里面,下面是概念页面大小的办法:

  • 率先种植概念一个版面大小的主意:
    通过定义像素或者英寸定义一个页面尺寸。注意:在iTextSharp中页面大小的单位是‘point。72point=1英寸。假设我们需要一个涨幅=2英寸&高度=10英寸的PDF文件,那么我们用144pt&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 对象
(任意一个)也即是端的 ‘rec’,或者 ‘rec2’要
‘rec3’加入iTextSharp.text.Document‘s 的构造函数中:

Document doc = new Document(rec);

设置PDF文档背景色:

发生几种植方式来安装背景色:

  • 首先栽办法:
    用用对象 iTextSharp.text.BaseColor. 实例化BaseColor
    采用System.Drawing.Color
    (.NET)对象要您吧足以用传递RGB值的款型来定义:

    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作为单位的,并且 72 points = 1 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()主意创建新页面,我们来创造5只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.

参考文献

  • iText Official Website
  • iText in Action, Second
    Edition
  • Core iText API Documentation
  • RubyPdf Blog – iText# in
    Action
  • Create PDFs in ASP.NET – getting started with
    iTextSharp
  • Basic PDF Creation Using iTextSharp – Part
    I

历史

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)

 

相关文章