iTextを使用してPDFを生成

13376 ワード

PDF操作クラスライブラリiText
iTextは、PDFファイルをすばやく生成できるJavaクラスライブラリとして有名です.テキスト、テーブル、グラフィックの操作をサポートし、サーブレットと簡単に結合できます.
iTextの更新は大きく変わり、以前のバージョンではPDFスタイルに欠陥がある可能性があり、私が使用した最新の5.5.6パック
1.Maven依存の追加
itextコアパッケージとxmlworderフォントパッケージ
<dependency>  
    <groupId>com.itextpdf</groupId> 
    <artifactId>itextpdf</artifactId> 
    <version>5.5.6</version>
</dependency>
<dependency>
   <groupId>com.itextpdf.tool</groupId>
   <artifactId>xmlworker</artifactId>
   <version>5.5.6</version>
</dependency>

2.直接pdfを生成する
非常に簡単で、文字で段落などを作成し、フォント、間隔、位置合わせなどを設定すればいいので、Hello Worldの例を作ってみましょう.
package iText;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfPHeaderCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import org.junit.Test;
import java.io.FileOutputStream;
/**
 * author wangnian
 * date 2016/4/1
 */
public class PdfDemo_1 {

    private static void create() throws Exception {

        //       (    A4,  36, 36, 36, 36)
        Document document = new Document();  
        //         
        document.setPageSize(PageSize.A4);  
        //     ,      ,    1  =28.33    
        document.setMargins(50, 50, 50, 50);
        //   pdf     
        FileOutputStream fileOutputStream= new FileOutputStream("D:/demo.pdf");
        //   writer,  writer       
        PdfWriter writer = PdfWriter.getInstance(document,fileOutputStream);
        // demo
        String title = "   ";
        String content = "       ,       。       ,       。";
    
        //       
        FontFactoryImp ffi = new FontFactoryImp();  
        //           ,windows    fonts    ,              
        ffi.registerDirectories();  
        //     ,        ,         
        Font font = ffi.getFont("  ",BaseFont.IDENTITY_H,BaseFont.EMBEDDED, 12, Font.UNDEFINED, null);  
    
        //     ,               
        document.open();  
    
        //       
        document.addAuthor("    ");
        //        
        document.addCreator("wangnian");
        //       
        document.addSubject("  ");
        //       
        document.addTitle("   ");
    
        //         
        document.add(new Paragraph(title, font));  
        document.add(new Paragraph(content, font));  
        document.add(new Paragraph("
\r", font));                //  ,5            PdfPTable table = new PdfPTable(4);           table.setTotalWidth(PageSize.A4.getWidth()- 100);           table.setLockedWidth(true);           //             PdfPHeaderCell header = new PdfPHeaderCell();           header.addElement(new Paragraph(title, font));           header.setColspan(4);           table.addCell(header);           //             table.addCell(new Paragraph(" ",font));         table.addCell(new Paragraph(" ",font));         table.addCell(new Paragraph(" ",font));         table.addCell(new Paragraph(" ",font));              document.add(table);           //  ,            document.close();           writer.close();      }       @Test    public  void test()  {        try {            create();            System.out.println(" ");        }catch (Exception ex){            System.out.println(" ");        }    } }

3.フォント
私达のプロジェクトの文书の字体は比较的に特殊で、例えば宋体(99%はすべてこれでしょう)、中国语は宋(officeをインストールした后に持参します)、宋をまねます_GB 2312など、pdfフォントを研究しましたが、ネット上では中国語フォントを使う方法がたくさんありますが、5.0版以降のiTextにフォントを入れるのは便利です.
package iText;
import java.io.FileOutputStream;
import com.itextpdf.text.Document;  
import com.itextpdf.text.Font;  
import com.itextpdf.text.FontFactoryImp;  
import com.itextpdf.text.Paragraph;  
import com.itextpdf.text.pdf.PdfWriter;  
import com.itextpdf.tool.xml.XMLWorkerFontProvider;
import org.junit.Test;

/** 
 *    
 * 
 * author wangnian
 * date 2016/4/1
 * 
 */  
public class PdfDemo_2 {  
    
    public static void create() throws Exception {  
        Document document = new Document();  
        PdfWriter writer = PdfWriter.getInstance(document,new FileOutputStream("D:/demo2.pdf"));
        String title = "   ";  
        String content = "       ,       。       ,       。";  
        document.open();  
        document.add(new Paragraph(title, getFont("       ")));
        document.add(new Paragraph(content, getFont("      ")));
        document.close();  
        writer.close();  
    }  
    
    private static Font getFont(String fontName) {  
        // xmlworker     html pdf  ,    ,  itext     
    
        //    xmlworker         ,   ,         
        FontFactoryImp fp = new XMLWorkerFontProvider();
        //          ,              ,      src/font    
        fp.registerDirectory(PdfDemo_2.class.getClassLoader().getResource("weiruanyahei").getFile(), true);
    
        //                    
        return fp.getFont(fontName);  
    
        //   ,          XMLWorkerFontProvider,        ,      
    }  

    @Test
    public void test() throws Exception {
        create();
        System.out.println("    ");
    }  
}

xmlworkerのXML WorkerFontProviderは、フォントの入手に便利です.
     1.フォルダを登録して、中にどんなフォントがあってもいいです.例えば、私のdemoのフォントです.
     2.getFont(フォント名)で入手できますが、フォント名はどこから来たのでしょうか
4.ヘッダー・フッター
iText 5では、以前のバージョンのHeaderFooterオブジェクトでヘッダーとフッターが設定されていません.PdfPageEventを使用してヘッダーのフッターの設定を完了できます.
PdfPageEventは、作成時のpdfのイベントをいくつか提供し、ヘッダー・フッターは各ページにロードされて書き込みが完了します.
ページごとにページ番号を付けるのは簡単ですが、総ページ番号を表示するのは面倒です.iTextはストリームモードの書き込み内容です.最後まで書いてこそ、何ページあるかがわかります.では、総ページ数を表示するのは面倒ですが、面倒は不可能ではありません.
iTextは、リリーステンプレートメソッドを呼び出した後にのみPdfTemplateをOutputStreamに書き込みます.そうしないと、ドキュメントを閉じるまでオブジェクトはメモリに保存されます.
したがって、最後にドキュメントを閉じる前に、PdfTemplateを使用して総ページ番号を書き込むことができます.まずプレースホルダを書いてから、統一的に置き換えることができます.
ハローワールドの例です
package iText;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import com.itextpdf.tool.xml.XMLWorkerFontProvider;
/**
 * iText5        HeaderFooter         <br> 
 *   ,    PdfPageEventHelper            。<br> 
 *                   ,    、  、   。<br> 
 * 
 * author wangnian
 * date 2016/4/1
 * 
 */  
   public class MyHeaderFooter extends PdfPageEventHelper {
    Font font = new XMLWorkerFontProvider().getFont("  ", 12, BaseColor.RED);
    //      
    PdfTemplate totalPage;
    //      ,            
    public void onOpenDocument(PdfWriter writer, Document document) {
        PdfContentByte cb =writer.getDirectContent();
        totalPage = cb.createTemplate(30, 16);  
    }  
    //         ,         
    public void onEndPage(PdfWriter writer, Document document) {
        PdfPTable table = new PdfPTable(3);
        try {  
            table.setTotalWidth(PageSize.A4.getWidth() - 100);
            table.setWidths(new int[] { 24, 24, 3});  
            table.setLockedWidth(true);  
           table.getDefaultCell().setFixedHeight(-10);  
           table.getDefaultCell().setBorder(Rectangle.BOTTOM);
   
            table.addCell(new Paragraph("    ", font));//       addCell(str),        ,      
           table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_RIGHT);  
            table.addCell(new Paragraph(" " + writer.getPageNumber() + " /", font));  
            //      
            PdfPCell cell = new PdfPCell(Image.getInstance(totalPage));  
            cell.setBorder(Rectangle.BOTTOM);  
            table.addCell(cell);  
            //      document ,      ,           
            table.writeSelectedRows(0, -1, 50,PageSize.A4.getHeight() - 20, writer.getDirectContent());  
        } catch (Exception de) {  
            throw new ExceptionConverter(de);  
        }  
    }  
   
    //      ,     pdf          
    public void onCloseDocument(PdfWriter writer,Document document) {  
        String text = " " + (writer.getPageNumber() - 1) + " ";  
        ColumnText.showTextAligned(totalPage, Element.ALIGN_LEFT, new Paragraph(text,font), 2, 2, 0);  
    }  
}
package iText;
import java.io.FileOutputStream;
import com.itextpdf.text.BaseColor;  
import com.itextpdf.text.Document;  
import com.itextpdf.text.Element;  
import com.itextpdf.text.ExceptionConverter;  
import com.itextpdf.text.Font;  
import com.itextpdf.text.Image;  
import com.itextpdf.text.PageSize;  
import com.itextpdf.text.Paragraph;  
import com.itextpdf.text.Rectangle;  
import com.itextpdf.text.pdf.ColumnText;  
import com.itextpdf.text.pdf.PdfContentByte;  
import com.itextpdf.text.pdf.PdfPCell;  
import com.itextpdf.text.pdf.PdfPTable;  
import com.itextpdf.text.pdf.PdfPageEventHelper;  
import com.itextpdf.text.pdf.PdfTemplate;  
import com.itextpdf.text.pdf.PdfWriter;  
import com.itextpdf.tool.xml.XMLWorkerFontProvider;
import org.junit.Test;

/** 
 *   、   
 * author wangnian
 * date 2016/4/1
 */
public class PdfDemo_3 {  
   
    public static void create() throws Exception {  
        Document document = new Document(PageSize.A4, 50, 50, 50, 50);
        PdfWriter writer = PdfWriter.getInstance(document,new FileOutputStream("d:/demo3.pdf"));
   
        //         
        writer.setPageEvent(new MyHeaderFooter());
   
        String title = "   ";  
        String content = "       ,       。       ,       。";  
        document.open();  
   
        Font font = new XMLWorkerFontProvider().getFont("  ");
        for (int i = 0; i <100; i++) {  
            document.add(new Paragraph(title, font));
            document.add(new Paragraph(content,font));  
            document.add(new Paragraph("
"));           }           document.close();           writer.close();       }       @Test     public  void test() throws Exception {         create();         System.out.println(" ");     }   }

5.html回転pdf
結果は悪くなくて、私達の要求を満たすことができますが、しかし比較的に複雑で、動的に1つの表と内容を作成するのは煩雑で、方法はあまりにも乱暴で、ユーザーのドキュメントの内容あるいはフォーマットの変化、プログラムを修正します.
htmlを作成してpdfに変換し、demoは次のようにします.
package iText;

import java.io.ByteArrayInputStream;
import java.io.FileOutputStream;  
import java.io.InputStream;  
import java.io.OutputStream;  
import com.itextpdf.text.Document;  
import com.itextpdf.text.pdf.PdfWriter;  
import com.itextpdf.tool.xml.XMLWorkerHelper;
import org.junit.Test;

/** 
 * html pdf
 * author wangnian
 * date 2016/4/1
 * 
 */  
public class PdfDemo_4 {  
    
    public static void create() throws Exception {  
    
        // html         
        // 1. html      ,         ,      。  
        // 2. html             ,   :font-family:SimSun;  
        // 3. html          ,    itext     ,  itext       ,             
        // 4.        html          ,                ,      
    
        StringBuilder html = new StringBuilder();
        html.append("<html>");  
        html.append("<body style='font-size:20px;font-family:SimSun;'>");
        html.append("<table width='19cm'border='1' cellpadding='0' cellspacing='0'>");  
        html.append("<tr>");  
        html.append("<td colspan='2'>   </td>");  
        html.append("</tr>");  
        html.append("<tr>");  
        html.append("<td>       ,       。</td>");  
        html.append("<td>       ,       。</td>");  
        html.append("</tr>");  
        html.append("</table>");  
        html.append("</body>");  
        html.append("</html>");  
    
        InputStream is = new ByteArrayInputStream(html.toString().getBytes());
    
        OutputStream os = new FileOutputStream("D:/demo4.pdf");
        Document document = new Document();  
    
        PdfWriter writer = PdfWriter.getInstance(document,os);  
    
        document.open();  
    
        //  html pdf  
        XMLWorkerHelper.getInstance().parseXHtml(writer,document, is);  
    
        document.close();  
    }  

    @Test
    public  void test() throws Exception {
        create();
        System.out.println("    ");
    }  
}

ここではXmlWorkerを使用していますが、XmlWorkerもiText公式で、現在iTextバージョンとともに更新されています.XHTMLをpdfに変換し、ほとんどのスタイルとラベルをサポートしていますが、ほとんどではありません.すべてではありません.     
現在、htmlドキュメントを書き、html内のタグビットを動的に置き換えてpdfを生成する方法を使用しています.   
 
XHTMLを使用してpdfを転送する際の注意点:
     1. htmlにフォントを指定しないと、デフォルトでは英語のフォントが使用され、中国語は表示されません.
     2. htmlで指定したフォントは英語名でなければなりません.宋体:font-family:SimSun;正しいfont-family:宋体;するとエラーで、unicodeもだめだった.   
     3. htmlではカスタムフォント(例えば、上の方正蘭亭黒)を指定することはできませんが、itextの一般的なオペレーティングシステムのフォントはサポートされています.ubuntuにマイクロソフトの黒がなければ、windowsから黒のフォントYaheiをコピーすることができます.ttfはubuntuに/usr/share/fonts/パスを入れます.     
     4. pdfに画像を追加するのも簡単です.例えば、,でいいです. 
    5. XHTMLはHTMLではないので、
エラーなどのラベルはすべて完全に終了しなければなりません.   
htmlのテンプレートを書くのは簡単で、htmlとcssに熟練する必要があります.生成されたスタイルの部分を調整するのは面倒です(例えば、文字が多くなると切ります.切らないと全体のスタイルに影響します.表の線が太くて細いので、xmlworkerはすべてのcssをサポートしません).一般的にA 4紙はセンチメートル単位で、htmlの中でもセンチメートルを使ったほうがいいです.処理は簡単です.