Html转Pdf文档入门汇总

来源:互联网 发布:bestbuy 知乎 编辑:程序博客网 时间:2024/05/29 19:16
 

目录

Html转Pdf文档...1

转化方式说明...2

PDF文件格式介绍...2

PDF类型...2

PDF文件结构可分为以下几块:4

header4

body.4

Cross reference table.4

trailer:5

ItextSharp...5

代码片断如下:...5

添加引用空间...5

变量声名:6

生成bitmap.6

生成PDF.6

代码说明...7

完整的代码...8

ABCPdf11

关于ABCpdf11

使用说明...11

Hellow World.12

HTML to PDF代码示例...12

首先创建Doc对象和设置边框....13

添加页并添加网页...13

把网页全部显示在页面上...13

让网页上的所有连接有效...13

保存文档...13

...14

完整的HTML转PDF类示例...14

Pdflib介绍...15


转化方式说明

方式一: 把HTML转成图片,然后把图片添加到PDF文档中.

方式二: 自己解析HTML、CSS等,像写HTML哪样添加文本,画表格,画图,添加图片,设置相应的样式等.

方式三: 给一个URL由第三方开发库直接把网页解析,按照网页的样式设置PDF文档样式,相当于方式二不同的是,方式二是自己解析HTML、CSS等,自己在PDF文档中画与HTML元素相对应内容; 而方式是完全由第三方开发库完成你只需要给他一个URL.

介绍3个开发库

ItextSharp: HTML转PDF方式有,1,2

ABCpdf: HTML转PDF方式有,1,2,3

其它可用库: Pdflib

PDF文件格式介绍

pdf(Portable   Document   Format,便携式文档结构)是一种很有用的文件格式,其最大的特点是平台无关而且功能强大(支持文字/图象/音乐/视频).先讲一下pdf的文件(物理)结构.

PDF类型

pdf里面8种类型.

Ø  1.booleam

用关键字truefalse表示,可以是array对象的一个元素,dictionary对象的一个条目.

Ø  2.numeric

1.    包括整形和实型,不支持非十进制数字,不支持指数形式的数字.

:
  1)
整数 123 4567 +111 -2    
 
范围:231次方-1到负的231次方
  2)
实数 12.3 0.8 +6.3 -4.01 -3. +.03
 
范围:±3.403 × 1038次方     ±1.175 × 10-38次方
 
注意:如果整数超过表示范围将转化成实数,如果实数超过范围就出错了

Ø  3.string

由一系列0-255之间的字节组成,一个string总长度不能超过65535.string有以下两种方式:
  1)
()包含起来的一个字串,中间可以使用转义符"/".
 
:
  (abc) 
表示abc
  (a//) 
表示a/
  2)
<>包含起来的一个16进制串,两位表示一个字符,不足两位用补齐
 
:
  <Aabb> 
表示AABB两个字符
  <AAB> 
表示AAB0两个字符

Ø  4.name

由一个前导/和后面一系列字符组成,最大长度为127.string不同的是,name是不可分割的
 
和唯一的,不可分割就是说一个name对象就是一个原子,比如/name,不能说n就是这个name一个元素;唯一就是指两个相同的name一定代表同一个对象.pdf1.2开始,除了ascii0,别的都可以用一个#加两个十六进制的数字表示.
 
:
  /name 
表示name
  /name#20is
表示name is
  /name#200
表示name 0

/string 表示string

Ø  5.array

[]包含的一组对象,可以是任何pdf对象(包括array).虽然pdf只支持一维array,但可以通过
  array
的嵌套实现任意维数的array(但是一个array的元素不能超过8191)
 
:
  [549 3.14 false (Ralph) /SomeName]

Ø  6.Dictionary

"<<"">>"包含的若干组条目,每组条目都由keyvalue组成,其中key必须是name对象,并且
 
一个dictionary内的key是唯一的;value可以是任何pdf的合法对象(包括dictionary对象).
 
:
  << /IntegerItem 12
  /StringItem (a string)
  /Subdictionary << /Item1 0.4
  /Item2 true
  /LastItem (not!)
  /VeryLastItem (OK)
  >>
  >>

Ø  7.stream

由关键字streamendstream包含一系列字节.内容和string很相似,但有区别:stream可以分几次
 
读取,分开使用不同的部分,string必须作为一个整体一次全部读取使用;string有长度限制,
  stream
却没有这个限制.一般较大的数据都用stream表示.

Ø  8.NULL

null表示,代表空.如果一个key的值为null,则这个key可以被忽略;如果引用一个不存在的
  object
则等价于引用一个空对象.

给大家说点有用的东西:为什么有的pdf不允许打印?
pdf
有自己的加密措施,其中就有限制打印.
找到trailer,如果这个pdf是加密的话会有一个/Encryptname,他的值一般形式是n 0 R,表示这个pdf
文件的加密信息在n 0这个obj里面记录.找到这个obj,其下有一个/Pname,他的值是一个数字(32)其中第三位代表是否有打印权限.

PDF文件结构可分为以下几块:

header

pdf文件的第一行,格式如下:  
  %PDF-1.3  
表示当前文件的版本是1.3(目前最高版本是多少未知),软件的版本号总要比文件格式的版本号高1,比如说Read 5能打开的内容就是4

body

pdf文件中用到的所有对象,包括文本/图象/音乐/视频/字体/超连接/加密信息等等,格式如下:

2   0   obj  
   ...  
   end   obj  
   其中省略号部分是pdf规定的任意合法对象(一共8)  

例如:

30979 0 obj

<<

/Linearized 1

/O 30982

/H [ 15061 25084 ]

/L 9379963

/E 166967

/N 978

/T 8760262

>>

endobj

第一个数字就是这个OBJ的顺序号,是为了便于在xref中查找,后面的是为了区分不同的OBJ,后面就是关键字obj.下面的各行就是属性,/关键字值的形式。

Cross reference table

所有pdf对象的引用表,其格式如下
  xref  
   0   5  
   0000000000   65535   f  
   0000000009   00000   n  
   0000000074   00000   n  
   0000000120   00000   n  
   0000000179   00000   n  
   其中,xref是开始标志,表示以下为引用表内容;0   5表示从对象号为的开始连续有5个对象(0,1,2,3,4),分别用5行来表示.每行的前10个数字代表这个这个对象相对文件头的偏移地址,后面5个数字只有当这个对象被删除的时候才有用,表示这个对象被删除后又被重新生成后的对象号最后一位fn表示对象是否被使用(n表示使用,f表示被删除或没有用)  

trailer:

位于PDF文件的未尾.整个pdf文件的入口点,形式如下:  
       trailer  
      <<  
      /Size   8  
      /Root   1   0   R  

/ID [<B29FBB52459C4623DB1A90CBFC28381E><B29FBB52459C4623DB1A90CBFC28381E>]
   >>  

   startxref  
   553  
   %%EOF  

说明:

  /size:  这个pdf中总共使用了多少个对象
      /root:  这个pdf文件的catalog对象的对象号,这是pdf中最顶层的对象
      /startxref:   后面的数字表示cross   reference   table的开始位置
      /%%EOF   :文件结束符.  

/ID 是为了让一些文件检索工具能够唯一区分文件。

ItextSharp库

库文件: itextsharp.dll

HTML生成PDF文件有2种方式

第一种: 像写HTML代码哪样, 用C#往文件流中输出表格,添加文本添加图片等,自己排版.

第二种: 先把HTML生成图片,在向PDF文档中添加图片

这里只介绍第2种方式.

代码片断如下:

添加引用空间

using iTextSharp.text.pdf;

using iTextSharp.text;

using System.Windows.Forms;

using System.IO;

变量声名:

System.Drawing.Bitmap bitmap;

Document document; // ItextShart文档对象,核心对象

string url;

int w, h; // 宽高

生成bitmap

    using (WebBrowser wb =new WebBrowser())

    {

        wb.ScrollBarsEnabled = false;

        wb.Navigate(url); //不支持file:///F:/m.mht 这种文件地址形URL

        //确保全部解析完毕

        while (wb.ReadyState != WebBrowserReadyState.Complete)

        {

            System.Windows.Forms.Application.DoEvents();

        }

       //获取解析后HTML的大小

        System.Drawing.Rectangle r = wb.Document.Body.ScrollRectangle;

        w = r.Width;

        h = r.Height;

       //设置解析后HTML的可视区域,说明:这里的可视区域小于HTML页面的实际大小的话会有滚动条,生成的图片也有滚动条;如果这里的可视大于HTML页面的实际大小,生成的图片下方与右方会有空白

        wb.Width = w;

        wb.Height = h;

        bitmap = new System.Drawing.Bitmap(w, h);

        wb.DrawToBitmap(bitmap, new System.Drawing.Rectangle(0, 0, w, h));

    }

生成PDF

     using (MemoryStream ms =new MemoryStream())

      {             

          // 创建PDF的文档对象,PDF文档生成核心对象

           doc = new Document(new Rectangle(0, 0, w, h), 0, 0, 0, 0);//

  // PDF输出流对象

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

           writer.CloseStream = false;            

           doc.Open();                         

           iTextSharp.text.Image img = iTextSharp.text.Image.GetInstance(bitmap, System.Drawing.Imaging.ImageFormat.Jpeg);            

           img.ScalePercent(100); //图片放缩

          //PDF文档中添加对象

           doc.Add(img);            

           doc.Close(); //

           return ms.ToArray();            

       }

代码说明

Ø  第一步:创建一个 iTextSharp.text.Document对象的实例:

Document document = newDocument(new Rectangle(0, 0, w, h), 0, 0, 0, 0);

W为宽,H为高.

Document的后边4个参数分别代表左右上下边距.

Rectangle声名如下:

        ///<summary>

        /// Constructs a Rectangle-object.

        ///</summary>

        ///<param name="llx">lower left x</param>

        ///<param name="lly">lower left y</param>

        ///<param name="urx">upper right x</param>

        ///<param name="ury">upper right y</param>

        public Rectangle(float llx,float lly, float urx,float ury);

Document声名如下:

        ///<summary>

        /// Constructs a new Document-object.

        ///</summary>

        ///<param name="pageSize">the pageSize</param>

        ///<param name="marginLeft">the margin on the left</param>

        ///<param name="marginRight">the margin on the right</param>

        ///<param name="marginTop">the margin on the top</param>

        ///<param name="marginBottom">the margin on the bottom</param>

        public Document(Rectangle pageSize,float marginLeft, float marginRight,float marginTop, float marginBottom)

Ø  第二步,创建输出流

可以使用以下任何3,不知道是否还有其它什么可以写入的流

1.  内存流

MemoryStream ms = new MemoryStream();

2.  文件流

FileStream fs =FileStream("Chap0101.pdf",FileMode.Create)

3.  写入流

StreamWriter sw = new StreamWriter("out1.pdf");

Ø  第三步,为该Document创建一个Writer实例

PdfWriter writer = PdfWriter.GetInstance(document, ms);

说明: document为第一步创建的Document实例, ms为第二步创建的输出流.

GetInstance的声名:

        /**

* Use this method to get an instance of the <CODE>PdfWriter</CODE>.

*

* @param    document    The <CODE>Document</CODE> that has to be written

* @param    os  The <CODE>Stream</CODE> the writer has to write to.

* @return   a new <CODE>PdfWriter</CODE>

*

* @throws   DocumentException on error

*/

       

        public staticPdfWriter GetInstance(Document document,Stream os)

Ø  第四步,打开当前Document

document.Open();

Ø  第五步,创建图片对像

iTextSharp.text.Image img = iTextSharp.text.Image.GetInstance(bitmap, System.Drawing.Imaging.ImageFormat.Jpeg);

Image.GetInstance函数声名:

///<summary>

/// Converts a .NET image to a Native(PNG, JPG, GIF, WMF) image

        ///</summary>

        ///<param name="image"></param>

        ///<param name="?"></param>

        ///<returns></returns>

        public staticImage GetInstance(System.Drawing.Image image, System.Drawing.Imaging.ImageFormat format)

Ø  第六步,Document中添加Image对象

document.Add(img);

Ø  第七步,关闭Document

document.Close();

PDF文档写入trailer, cross reference table(所有pdf对象的引用表)PDF文档的信息

完整的代码

using System;

using iTextSharp.text;

using System.IO;

using System.Threading;

using iTextSharp.text.pdf;

using System.Windows.Forms;

namespace MiniItextSharp

{

    class Program

    {

        public classHTML2PDF

        {

            private System.Drawing.Bitmap bitmap;

            private string url;

            private Document doc;

            private int w = 0, h = 0;

            public void SetBitMap()

            {

                using (WebBrowser wb =new WebBrowser())

                {

                    wb.ScrollBarsEnabled = false;

                    wb.Navigate(url); //不支持file:///F:/m.mht 这种文件地址形URL

                    //确保页面被解析完全

                    while (wb.ReadyState != WebBrowserReadyState.Complete)

                    {

                        System.Windows.Forms.Application.DoEvents();

                    }

                    // 获取HTML的实际大小

                    System.Drawing.Rectangle r = wb.Document.Body.ScrollRectangle;

                    w = r.Width;

                    h = r.Height;

                    // 设置可视区域,太大,会有空白,太小会有滚动条

                    wb.Width = w;

                    wb.Height = h;

                    bitmap = new System.Drawing.Bitmap(w, h);

                    wb.DrawToBitmap(bitmap, new System.Drawing.Rectangle(0, 0, w, h));

                    bitmap.Save("t.bmp");

                }

            }

            public byte[] CreatPdf()

            {

               

                try

                {

                    url = "http://localhost/m.mht";

                    Thread thread = new Thread(newThreadStart(SetBitMap));

                    thread.SetApartmentState(ApartmentState.STA);

                    thread.Start();

                    while (thread.IsAlive)

                        Thread.Sleep(100);

                    using (MemoryStream ms =new MemoryStream())

                    {

                        doc = new Document(new Rectangle(0, 0, w, h), 0, 0, 0, 0);//左右上下

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

                        writer.CloseStream = false;

                        doc.Open();

                        iTextSharp.text.Image img = iTextSharp.text.Image.GetInstance(bitmap, System.Drawing.Imaging.ImageFormat.Jpeg);

                        img.ScalePercent(100);//放缩比例

                        doc.Add(img); // 添加对像

                        doc.Close();  //写入PDF文档对象的引用表,trailer

                        return ms.ToArray();

                    }

                }

                catch (Exception err)

                {

                    throw new Exception(err.Message);

                }

            }

        }

        static void Main(string[] args)

        {

            HTML2PDF test = new HTML2PDF();

            FileStream file = new FileStream("out.pdf",FileMode.Create);

            byte[] result = test.CreatPdf();

            file.Write(result, 0, result.Length);

            file.Close();

        }

    }

}

ABCPdf

关于ABCpdf

Adobe PDF功能实现是独立的控件。因为它不依赖于任何打印驱动程序,直接生成PDF,所以速度非常之快。

因为它是完全的多线程机制,你可以在ASPX, ASP, VB, C#开发环境和COM+, MTS or .NET 企业服务平台下灵活使用。

它实际上融合了你可能会需要的任何一个功能。然而我们必须注意防止过多地载入对象,以保证使用的简单,优雅和方便。

因为ABCpdf不依赖于任何其他的软件,所以它可以实现完全的多线程,而且不会出现任何令人不悦的瓶颈效果。

ABCpdf.NET是一个能够很方便生成pdf的.net组件,能够运行在以下操作系统中:Windows 2000, Windows XP, Windows Server 2003, Windows Vista, and Windows Server 2008.官方建议运行环境安装IE6或者以上版本。对应不同的系统,它有32位和64位的版本,使用时注意版本的选用。

ABCpdf的功能比较 多,比如可以读word、excel等文件,可以保存pdf、xps、swf等格式文件。本文主要介绍其生成pdf的方法。使用时,需要 ABCpdf.DLL和ABCpdfCE7.DLL支持。其中ABCpdf.DLL(.net调用接口)需要引用到项目 中,ABCpdfCE7.DLL(核心驱动)放在ABCpdf.DLL的同一目录下即可。

ABCpdf的坐标系采用Adobe PDF标准坐标系,原点在屏幕的左下角,采用72DPI(我们用的通常是96DPI,在计算大小时注意转换,网页面上的96px相当于ABCpdf里面72px)

使用说明

1.       ABCPdf有32位于64位版本区分,在32位系统下需用32位的ABCpdf,64位的系统下需用64位系统

2.       拷贝….到使用的目录

3.       安装ABCPdf

4.       命名空间

using WebSupergoo.ABCpdf8;
using WebSupergoo.ABCpdf8.Objects;
using WebSupergoo.ABCpdf8.Atoms;
using WebSupergoo.ABCpdf8.Operations;

1)  WebSupergoo.ABCpdf8

包含了页面布局的对象,多数时候,仅仅引用这一个空间就足够.

2)  WebSupergoo.ABCpdf8.Objects

包含那些访问和操作你已经添加内容的对象

3)  WebSupergoo.ABCpdf8.Atoms

包含低层访问原生PDF数据结构的对象

4)  WebSupergoo.ABCpdf8.Operations

此命名空间允许你多个参数和回调进行复杂操作

Hellow World

       创建一个PDF文档很简单. 首先创建Document对象,然后向Document对象实例添加内容, 可以是文本,图片,其它类型的图形.

       当在当前页面的内框中添加了所有想添加的内容,可以改变页码添加新的内容.默认是第一页,默认的内框大小为整个页面.

       可以使用FrameRect设置当前页面内框的大小.

       每次向Document对象实例中添加完内容后都会返回该内容对应的ID,可以保存该ID,方便以后对添加的内容进行查询与属性修改.

       示例:

Doc theDoc = new Doc();
theDoc.FontSize = 96;
theDoc.AddText("Hello World");
theDoc.Save(Server.MapPath("simple.pdf"));
theDoc.Clear();

图:


simple.pdf

HTML to PDF代码示例

英文原文: ABCpdf.Net手册中对应目标为:

ABCpdf8>

Examples>

Paged HTML Example

首先创建Doc对象和设置边框.

Doc theDoc = new Doc();
theDoc.Rect.Inset(72, 144);

72: 左边和右边分别与边框的边距为72.

144: 上边和下边分别与边框的边距为144.

添加页并添加网页

theDoc.Page = theDoc.AddPage();// 添加页面
int theID;
theID = theDoc.AddImageUrl("http://www.yahoo.com/"); // 向该页添加网页

把网页全部显示在页面上

while (true) {
theDoc.FrameRect(); // 添加边框
if (!theDoc.Chainable(theID)) // 看看是否还有没有添加完的内容
break; // 没有就结束
theDoc.Page = theDoc.AddPage(); // 如果有就添加新的一页
theID = theDoc.AddImageToChain(theID); // 根据ID添加内容并返回页面上该内容对应的新ID

}

让网页上的所有连接有效

for (int i = 1; i <= theDoc.PageCount; i++) {

theDoc.PageNumber = i;
theDoc.Flatten(); //使超连接有效

}

保存文档

theDoc.Save(Server.MapPath("pagedhtml.pdf")); // 保存文件名为:pagehtml.pdf
theDoc.Clear(); //清理数据

完整的HTML转PDF类示例

   public classAbcPdfBusiness : IPdf

    {

        private Doc pdf =null;

        private string url =null;

        public AbcPdfBusiness(string url)

        {

            XSettings.InstallRedistributionLicense("719-253-057");

            this.url = url;

           

            pdf = new Doc();

            pdf.MediaBox.String = "0 0 800 900";//页面大小

            pdf.Rect.String = "14 20 750 900"; // 内容的所在区间大小

                       

            pdf.HtmlOptions.HideBackground = false; //隐藏网页的背景(不是背景图)

            pdf.HtmlOptions.AddLinks = true; //使HTML链接有效()

            pdf.HtmlOptions.AddForms = true;  //是否可使HTML的Form有效.

            pdf.HtmlOptions.AddTags = true;

        }

        public byte[] ToBytes()

        {  

            int id = pdf.AddImageUrl(url, true, 1080, true);

           // 分页显示全部内容

            while (true)

            {

                if (!pdf.Chainable(id))

                    break;

                pdf.Page = pdf.AddPage();

                id = pdf.AddImageToChain(id);

            }

            pdf.HtmlOptions.LinkPages(); //把网页内部跳转转化为PDF内部跳转

            for (int i = 1; i <= pdf.PageCount; i++)

            {

                pdf.PageNumber = i;

                pdf.Flatten(); //重组和压缩页面的内容可以减少PDF的大小,向PDF文档中添加条目返回的ID在此之后无效,如: 上边代码id = pdf.AddImageToChain(id);中的ID

            }

            MemoryStream stream = new MemoryStream();

            pdf.Save(stream);

            return stream.ToArray();

        }

        public void Dispose()

        {

            if (pdf != null)

            {

                pdf.Clear();

                pdf.Dispose();

            }

        }

   

Pdflib介绍

pdflib也提供了一组sdk,但和adobesdk相比,pdflib很小,但功能却一点也不弱。所以对于开发者来说,pdflib是一个明智的选择。你可以从下面的网址得到到它:
      http://www.pdflib.com/products/pdflib/download/index.html。如果你没有得到序列号,那么生成的pdf将会加上水印,其他功能和商业版一样。
      另外你还可以从下面网址得到pdflib-lite版:
   http://www.pdflib.com/products/pdflib/download-source.html  
      pdflib-lite使用协议:
      http://www.pdflib.com/purchase/license-lite.html  
      pdflib相比,pdflib-lite最大的特点就是你可以拥有完全的源代码,但功能不如pdflib全面,比如支持的字体要比pdflib少很多。但是,如果你对pdf文件本身很了解的话,你完全可以在pdflib-lite的基础上再做发挥,这就要看你的c语言功底如何了。

下载pdflib压缩包(大约6m)后,在pdflib文件夹下有pdflib.dllpdflib.libpdflib.hpdflib.reg。对于我们来说,只要有前3个文件就可以了。