java操作pdf之iText快速入门
java操作pdf之iText快速入門
iText是著名的開放項(xiàng)目,是用于生成PDF文檔的一個(gè)java類庫。通過iText不僅可以生成PDF或rtf的文檔,而且可以將XML、Html文件轉(zhuǎn)化為PDF文件。
iText官網(wǎng): http://itextpdf.com/
官網(wǎng)示例: http://itextpdf.com/examples/
更多示例: https://kb.itextpdf.com/home/it5kb/examples
Maven依賴:
<!-- https://mvnrepository.com/artifact/com.itextpdf/itextpdf --><dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.13</version></dependency><!-- https://mvnrepository.com/artifact/com.itextpdf/itext-asian --><dependency><groupId>com.itextpdf</groupId><artifactId>itext-asian</artifactId><version>5.2.0</version></dependency>pdf和iText簡(jiǎn)介
第一個(gè)iText示例:Hello World
public class HelloWorld {public static final String RESULT= "src/main/resources/hello.pdf";/*** 創(chuàng)建一個(gè)pdf文件: hello.pdf*/public static void main(String[] args)throws DocumentException, IOException {new HelloWorld().createPdf(RESULT);}//五個(gè)步驟public void createPdf(String filename)throws DocumentException, IOException {// step 1Document document = new Document();// step 2PdfWriter.getInstance(document, new FileOutputStream(filename));// step 3document.open();// step 4document.add(new Paragraph("Hello World!"));// step 5document.close();} }自定義頁面大小
通過 Document構(gòu)造函數(shù)來設(shè)置頁面的大小尺寸和 頁面邊距。
Document(Rectangle pageSize, float marginLeft, float marginRight, float marginTop, float marginBottom)
其中通過 Rectangle(寬,高)來指定pdf頁面的尺寸大小,通過marginLeft marginRight marginTop marginBottom來設(shè)置頁面邊距.
Rectangle pagesize = new Rectangle(216f, 720f);Document document = new Document(pagesize, 36f, 72f, 108f, 180f);或者
通過PageSize.LETTER來指定頁面的大小。在實(shí)際開發(fā)中PageSize.A4使用的比較多。如果構(gòu)造不指定的話默認(rèn)就是PageSize.A4 頁邊距全是36pt。
Document document = new Document(PageSize.LETTER);常用屬性
//設(shè)置作者document.addAuthor("ZBK");//設(shè)置創(chuàng)建日期document.addCreationDate();// 設(shè)置創(chuàng)建者document.addCreator("張寶奎");// 設(shè)置生產(chǎn)者document.addProducer();// 設(shè)置關(guān)鍵字document.addKeywords("my");//設(shè)置標(biāo)題document.addTitle("標(biāo)題");//設(shè)置主題document.addSubject("主題");最大頁面尺寸
public class HelloWorldMaximum {public static final String RESULT = "src/main/resources/hello_maximum.pdf";public static void main(String[] args)throws DocumentException, IOException {// 第一步//最大頁面尺寸Document document = new Document(new Rectangle(14400, 14400));// 第二步PdfWriter writer =PdfWriter.getInstance(document, new FileOutputStream(RESULT));// 改變用戶單位 UserUnit是定義默認(rèn)用戶空間單位的值。最小UserUnit為1(1個(gè)單位= 1/72英寸)。最大UserUnit為75,000。writer.setUserunit(75000f);// step 3document.open();// step 4document.add(new Paragraph("Hello World"));// step 5document.close();}}橫向顯示pdf
通過**rotate()**方法
Document document = new Document(PageSize.LETTER.rotate());或者
通過設(shè)置寬和高
Document document = new Document(new Rectangle(792, 612));設(shè)置頁邊距和裝訂格式
? 對(duì)于需要裝訂成冊(cè)的多頁pdf,如果是左右裝訂(正反面打印)的話我們第一頁的左邊距要與第二頁的右邊距一樣,第一頁的右邊距要與第二頁的左邊距一樣,也就是保證頁邊距要對(duì)稱。
通過 setMargins設(shè)置頁邊距,通過setMarginMirroring(true) 來設(shè)置兩頁的邊距對(duì)稱
注意: 如果是上下裝訂的方式裝訂,則通過**setMarginMirroringTopBotton(true)**來設(shè)置兩頁的邊距對(duì)稱.
public class HelloWorldMirroredMargins {public static final String RESULT= "src/main/resources/hello_mirrored_margins.pdf";public static void main(String[] args)throws DocumentException, IOException {// step 1Document document = new Document();// step 2PdfWriter.getInstance(document, new FileOutputStream(RESULT));document.setPageSize(PageSize.A5);document.setMargins(36, 72, 108, 180);document.setMarginMirroring(true); //設(shè)置邊距對(duì)稱// step 3document.open();// step 4document.add(new Paragraph("The left margin of this odd page is 36pt (0.5 inch); " +"the right margin 72pt (1 inch); " +"the top margin 108pt (1.5 inch); " +"the bottom margin 180pt (2.5 inch)."));Paragraph paragraph = new Paragraph();paragraph.setAlignment(Element.ALIGN_JUSTIFIED);for (int i = 0; i < 20; i++) {paragraph.add("Hello World! Hello People! " +"Hello Sky! Hello Sun! Hello Moon! Hello Stars!");}document.add(paragraph);document.add(new Paragraph("The right margin of this even page is 36pt (0.5 inch); " +"the left margin 72pt (1 inch)."));// step 5document.close();} }內(nèi)存中操作pdf文件
public class HelloWorldMemory {public static final String RESULT = "src/main/resources/hello_memory.pdf";public static void main(String[] args)throws DocumentException, IOException {// step 1Document document = new Document();// step 2// we'll create the file in memoryByteArrayOutputStream baos = new ByteArrayOutputStream();PdfWriter.getInstance(document, baos);// step 3document.open();// step 4document.add(new Paragraph("Hello World!"));// step 5document.close();// let's write the file in memory to a file anywayFileOutputStream fos = new FileOutputStream(RESULT);fos.write(baos.toByteArray());fos.close();} }設(shè)置pdf版本
通過PdfWriter 的 setPdfVersion 方法來設(shè)置我們pdf的版本號(hào)
public class HelloWorldVersion_1_7 {public static final String RESULT = "src/main/resources/hello_1_7.pdf";public static void main(String[] args)throws DocumentException, IOException {// step 1Document document = new Document();// step 2// Creating a PDF 1.7 documentPdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(RESULT));writer.setPdfVersion(PdfWriter.VERSION_1_7);// step 3document.open();// step 4document.add(new Paragraph("Hello World!"));// step 5document.close();} }添加內(nèi)容
添加內(nèi)容也有兩個(gè)方法
- 往Document類中添加high-level的對(duì)象
- 直接用PdfWriter實(shí)例添加比較low-level的數(shù)據(jù)。
和以前代碼不同的是:我們將生成的PdfWriter實(shí)例保存到局部變量writer中。因?yàn)楹罄m(xù)要通過此writer來獲取canvas畫線畫圖。代碼中通過設(shè)置CompressionLevel屬性為0可以避免對(duì)輸出流的壓縮,我們也可以通過記事本來查看pdf的語法語句。以上canvas的每個(gè)方法后面的注釋對(duì)應(yīng)具體的pdf語法,大家用記事本打開就可以看到。
壓縮多個(gè)pdf文件
通過ZipEntry 將多個(gè)pdf壓縮成一個(gè)壓縮文件
public class HelloZip {public static final String RESULT = "src/main/resources/hello.zip";public static void main(String[] args)throws DocumentException, IOException {// creating a zip file with different PDF documentsZipOutputStream zip =new ZipOutputStream(new FileOutputStream(RESULT));for (int i = 1; i <= 3; i++) {ZipEntry entry = new ZipEntry("hello_" + i + ".pdf");zip.putNextEntry(entry);// step 1Document document = new Document();// step 2PdfWriter writer = PdfWriter.getInstance(document, zip);writer.setCloseStream(false);// step 3document.open();// step 4document.add(new Paragraph("Hello " + i));// step 5document.close();zip.closeEntry();}zip.close();} }添加新頁
document.newPage();添加水印
文字水印
public class PdfWaterMark {public static final String RESULT = "src/main/resources/font_water_mark.pdf";public static void main(String[] args) throws FileNotFoundException, DocumentException {Document document = new Document();PdfWriter pdfWriter = PdfWriter.getInstance(document, new FileOutputStream(RESULT));// 打開文檔document.open();// 加入水印PdfContentByte waterMar = pdfWriter.getDirectContentUnder();// 開始設(shè)置水印waterMar.beginText();// 設(shè)置水印透明度PdfGState gs = new PdfGState();// 設(shè)置填充字體不透明度為0.4fgs.setFillOpacity(0.4f);try {// 設(shè)置水印字體參數(shù)及大小 (字體參數(shù),字體編碼格式,是否將字體信息嵌入到pdf中(一般不需要嵌入),字體大小)waterMar.setFontAndSize(BaseFont.createFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.NOT_EMBEDDED), 60);// 設(shè)置透明度waterMar.setGState(gs);// 設(shè)置水印對(duì)齊方式 水印內(nèi)容 X坐標(biāo) Y坐標(biāo) 旋轉(zhuǎn)角度waterMar.showTextAligned(Element.ALIGN_RIGHT, "www.newland.com", 500, 430, 45);// 設(shè)置水印顏色waterMar.setColorFill(BaseColor.GRAY);//結(jié)束設(shè)置waterMar.endText();waterMar.stroke();} catch (IOException e) {e.printStackTrace();}// 加入文檔內(nèi)容document.add(new Paragraph("my first pdf demo"));// 關(guān)閉文檔document.close();pdfWriter.close();}}圖片水印
public class PdfWaterMark {public static final String RESULT = "src/main/resources/img_water_mark.pdf";public static void main(String[] args) throws FileNotFoundException, DocumentException {Document document = new Document();PdfWriter pdfWriter = PdfWriter.getInstance(document, new FileOutputStream(RESULT));// 打開文檔document.open();// 加入水印PdfContentByte waterMar = pdfWriter.getDirectContentUnder();// 開始設(shè)置水印waterMar.beginText();// 設(shè)置水印透明度PdfGState gs = new PdfGState();// 設(shè)置填充字體不透明度為0.4fgs.setFillOpacity(0.4f);try {Image image = Image.getInstance("D:\\Folder\\image\\logo.png");// 設(shè)置坐標(biāo) 絕對(duì)位置 X Yimage.setAbsolutePosition(200, 300);// 設(shè)置旋轉(zhuǎn)弧度image.setRotation(30);// 旋轉(zhuǎn) 弧度// 設(shè)置旋轉(zhuǎn)角度image.setRotationDegrees(45);// 旋轉(zhuǎn) 角度// 設(shè)置等比縮放image.scalePercent(30);// 依照比例縮放// image.scaleAbsolute(200,100);//自定義大小// 設(shè)置透明度waterMar.setGState(gs);// 添加水印圖片waterMar.addImage(image);// 設(shè)置透明度waterMar.setGState(gs);//結(jié)束設(shè)置waterMar.endText();waterMar.stroke();} catch (IOException e) {e.printStackTrace();}// 加入文檔內(nèi)容document.add(new Paragraph("hello world"));// 關(guān)閉文檔document.close();pdfWriter.close();}}給已經(jīng)存在的pdf添加文字水印
/*** 已有的pdf文件添加水印* @param inputFile:要加水印的源文件的路徑* @param outputFile:加水印后文件的輸出路徑* @param waterMarkName:要加的水印名*/ public static void waterMark(String inputFile,String outputFile, String waterMarkName) {try {PdfReader reader = new PdfReader(inputFile);PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(outputFile));BaseFont base = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);PdfGState gs = new PdfGState();//改透明度gs.setFillOpacity(0.5f);gs.setStrokeOpacity(0.4f);int total = reader.getNumberOfPages() + 1;JLabel label = new JLabel();label.setText(waterMarkName);PdfContentByte under;// 添加一個(gè)水印for (int i = 1; i < total; i++) {// 在內(nèi)容上方加水印under = stamper.getOverContent(i);//在內(nèi)容下方加水印//under = stamper.getUnderContent(i);gs.setFillOpacity(0.5f);under.setGState(gs);under.beginText();//改變顏色under.setColorFill(BaseColor.LIGHT_GRAY);//改水印文字大小under.setFontAndSize(base, 100);under.setTextMatrix(70, 200);//后3個(gè)參數(shù),x坐標(biāo),y坐標(biāo),角度under.showTextAligned(Element.ALIGN_CENTER, waterMarkName, 300, 350, 55);under.endText();}stamper.close();reader.close();} catch (Exception e) {e.printStackTrace();} }給已經(jīng)存在的pdf添加圖片水印
/*** @param inputFile:要加水印的源文件的路徑* @param outputFile:加水印后文件的輸出路徑* @param pocturePath: 圖片的位置*/ public static void pictureWaterMark(String inputFile, String outputFile, String pocturePath) {try {PdfReader reader = new PdfReader(inputFile);PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(outputFile));PdfGState gs = new PdfGState();//設(shè)置透明度gs.setFillOpacity(0.3f);gs.setStrokeOpacity(0.4f);int total = reader.getNumberOfPages() + 1;PdfContentByte waterMar;// 添加一個(gè)水印for (int i = 1; i < total; i++) {// 在內(nèi)容上方加水印waterMar = stamper.getOverContent(i);//在內(nèi)容下方加水印//under = stamper.getUnderContent(i);waterMar.setGState(gs);waterMar.beginText();Image image = Image.getInstance(pocturePath);// 設(shè)置坐標(biāo) 絕對(duì)位置 X Yimage.setAbsolutePosition(150, 250);// 設(shè)置旋轉(zhuǎn)弧度image.setRotation(30);// 旋轉(zhuǎn) 弧度// 設(shè)置旋轉(zhuǎn)角度image.setRotationDegrees(45);// 旋轉(zhuǎn) 角度// 設(shè)置等比縮放image.scalePercent(30);// 依照比例縮放// image.scaleAbsolute(200,100);//自定義大小// 添加水印圖片waterMar.addImage(image);// 設(shè)置透明度waterMar.setGState(gs);//結(jié)束設(shè)置waterMar.endText();waterMar.stroke();}stamper.close();reader.close();} catch (Exception e) {e.printStackTrace();} }pdf加密
首先要說明的是,itext中對(duì)pdf文檔的加密包括兩部分,第一部分是用戶密碼,第二部分是所有者密碼。這兩部分可以簡(jiǎn)單的理解為管理員密碼和用戶密碼,因此我們?cè)谠O(shè)置這兩個(gè)密碼的權(quán)限的時(shí)候,往往會(huì)將所有者密碼的權(quán)限級(jí)別設(shè)置的更高,而用戶密碼權(quán)限往往是“只讀”。
在之前的基礎(chǔ)上添加新的Maven依賴
<dependency><groupId>org.bouncycastle</groupId><artifactId>bcprov-jdk15on</artifactId><version>1.60</version> </dependency> public class PdfPassword {public static final String RESULT = "src/main/resources/password.pdf";public static void main(String[] args) throws FileNotFoundException,DocumentException {//實(shí)現(xiàn)A4紙頁面 并且橫向顯示(不設(shè)置則為縱向)Document document = new Document(PageSize.A4.rotate());PdfWriter pdfWriter = PdfWriter.getInstance(document,new FileOutputStream(RESULT));// 設(shè)置用戶密碼, 所有者密碼,用戶權(quán)限,所有者權(quán)限pdfWriter.setEncryption("userpassword".getBytes(), "ownerPassword".getBytes(), PdfWriter.ALLOW_COPY, PdfWriter.ENCRYPTION_AES_128);// 打開文檔document.open();// 加入文檔內(nèi)容document.add(new Paragraph("hello world"));// 關(guān)閉文檔document.close();pdfWriter.close();} }-
然后我們打開我們的pdf文檔,會(huì)彈出一個(gè)讓你輸入密碼的對(duì)話框,我們先用“userpassword”這個(gè)用戶密碼去打開。然后再查看文檔的屬性,具體如下:
-
我們可以看到,我們是無法對(duì)現(xiàn)在的這個(gè)pdf進(jìn)行打印和修改的。接下來,我們重新打開這個(gè)pdf。用“ownerPassword”這個(gè)密碼取打開。然后再查看文檔的屬性,具體如下:
權(quán)限參數(shù)
PdfWriter.ALLOW_MODIFY_CONTENTS
允許打印,編輯,復(fù)制,簽名 加密級(jí)別:40-bit-RC4
PdfWriter.ALLOW_COPY
允許復(fù)制,簽名 不允許打印,編輯 加密級(jí)別:40-bit-RC
PdfWriter.ALLOW_MODIFY_ANNOTATIONS
允許打印,編輯,復(fù)制,簽名 加密級(jí)別:40-bit-RC4
PdfWriter.ALLOW_FILL_IN
允許打印,編輯,復(fù)制,簽名 加密級(jí)別:40-bit-RC4
PdfWriter.ALLOW_SCREENREADERS
允許打印,編輯,復(fù)制,簽名 加密級(jí)別:40-bit-RC4
PdfWriter.ALLOW_ASSEMBLY
允許打印,編輯,復(fù)制,簽名 加密級(jí)別:40-bit-RC4
PdfWriter.EMBEDDED_FILES_ONLY
允許打印,編輯,復(fù)制,簽名 加密級(jí)別:40-bit-RC4
PdfWriter.DO_NOT_ENCRYPT_METADATA
允許打印,編輯,復(fù)制,簽名 加密級(jí)別:40-bit-RC4
PdfWriter.ENCRYPTION_AES_256
允許打印,編輯,復(fù)制,簽名 加密級(jí)別:256-bit-AES
PdfWriter.ENCRYPTION_AES_128
允許打印,編輯,復(fù)制,簽名 加密級(jí)別:128-bit-AES
PdfWriter.STANDARD_ENCRYPTION_128
允許打印,編輯,復(fù)制,簽名 加密級(jí)別:128-bit-RC4
PdfWriter.STANDARD_ENCRYPTION_40
允許打印,編輯,復(fù)制,簽名 加密級(jí)別:40-bit-RC4
使用iText的基本構(gòu)建快
? 現(xiàn)在我們將重點(diǎn)集中到第四步:添加內(nèi)容。這里說的添加內(nèi)容都是通過Document.Add()方法調(diào)用,也就是通過一些high-level的對(duì)象實(shí)現(xiàn)內(nèi)容的添加。這一節(jié)如標(biāo)題要介紹Chunk、Phrase、Paragraph和List對(duì)象的屬性和使用。Document的Add方法接受一個(gè)IElement的接口,我們先來看下實(shí)現(xiàn)此接口的UML圖:
Chunk 對(duì)象
? Chunk類是可以添加到Document中最小的文本片段。Chunk類中包含一個(gè)StringBuilder對(duì)象,其代表了有相同的字體,字體大小,字體顏色和字體格式的文本,這些屬性定義在Chunk類中Font對(duì)象中。其它的屬性如背景色(background),text rise(用來模擬下標(biāo)和上標(biāo))還有underline(用來模擬文本的下劃線或者刪除線)都定義在其它一系列的屬性中,這些屬性都可以通過settter 方法進(jìn)行設(shè)置.
public class CountryChunks {public static final String RESULT = "src/main/resources/country_chunks.pdf";public static void main(String[] args)throws IOException, DocumentException, SQLException {new CountryChunks().createPdf(RESULT);}public void createPdf(String filename)throws IOException, DocumentException, SQLException {// step 1Document document = new Document();// step 2PdfWriter.getInstance(document, new FileOutputStream(filename)).setInitialLeading(16);// step 3document.open();// step 4// add a country to the document as a Chunkdocument.add(new Chunk("China"));document.add(new Chunk(" "));Font font = new Font(Font.FontFamily.HELVETICA, 6, Font.BOLD, BaseColor.WHITE);Chunk id = new Chunk("cn", font);// with a background colorid.setBackground(BaseColor.BLACK, 1f, 0.5f, 1f, 1.5f);// and a text riseid.setTextRise(6);document.add(id);document.add(Chunk.NEWLINE);//換行 NEWLINE = new Chunk("\n");// step 5document.close();} }行間距: LEADING
使用Chunk類要注意的是其不知道兩行之間的行間距(Leading),這就是為什么在代碼中要設(shè)置InitialLeading屬性的原因。大家可以試著將其去掉然后再看下重新生存的pdf文檔:你會(huì)發(fā)現(xiàn)所有的文本都寫在同一行上。
SetTextRise
SetTextRise方法的參數(shù)表示的是離這一行的基準(zhǔn)線(baseline)的距離,如果為正數(shù)就會(huì)模擬上標(biāo),負(fù)數(shù)就會(huì)模擬為下標(biāo)。
Phrase 對(duì)象
Chunk類在iText是最小的原子文本,而Phrase類被定義為 “a string of word”,因此Phrase是一個(gè)組合的對(duì)象。轉(zhuǎn)換為java和iText來說,phrase就是包含了Chunk類的一個(gè)ArraryList。
Font bul = new Font(Font.FontFamily.TIMES_ROMAN, 12, Font.BOLD | Font.UNDERLINE); Font normal = new Font(Font.FontFamily.TIMES_ROMAN, 12);Phrase director = new Phrase(); director.Add(new Chunk("China", bul)); director.Add(new Chunk(",", bul)); director.Add(new Chunk("id", normal));document.add(director);Paragraph 對(duì)象
可以將Phrase和Paragraph類比HTML中的span和div。如果在前一個(gè)例子中用Paragraph代替Phrase,就沒有必要添加document.Add(Chunk.NEWLINE)。
Paragraph繼承Phrase類,因此我們?cè)趧?chuàng)建Paragraph類時(shí)和創(chuàng)建Phrase完全一致,不過Paragraph擁有更多的屬性設(shè)置:定義文本的對(duì)齊方式、不同的縮進(jìn)和設(shè)置前后的空間大小。
html轉(zhuǎn)為pdf
這里需要說明一個(gè)情況,如果項(xiàng)目中不引入字體文件,那么生成的pdf將不會(huì)顯示文字(因?yàn)樯a(chǎn)環(huán)境的服務(wù)器不會(huì)有任何字體文件,而本地運(yùn)行的話,會(huì)自動(dòng)去電腦中的字體文件庫中去尋找字體文件),因此,如果是需要發(fā)布的項(xiàng)目,務(wù)必將字體文件放到項(xiàng)目中,然后進(jìn)行使用。
引入Maven依賴
<dependency><groupId>org.xhtmlrenderer</groupId><artifactId>core-renderer</artifactId><version>R8</version> </dependency>index.html
<!DOCTYPE html> <html lang="en"> <head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"/><title>認(rèn)識(shí)table表標(biāo)簽</title><style type="text/css">/*解決html轉(zhuǎn)pdf文件中文不顯示的問題*/body {font-family: SimSun;}/*設(shè)定紙張大小*//* A4紙 *//* @page{size:210mm*297mm} */@page{size:a4}p {color: red;}</style> </head> <body><table border="1px"><caption>我的標(biāo)題</caption><tbody><tr><th>班級(jí)</th><th>學(xué)生數(shù)</th><th>平均成績(jī)</th><th>班級(jí)</th><th>學(xué)生數(shù)</th><th>平均成績(jī)</th><th>班級(jí)</th><th>學(xué)生數(shù)</th><th>平均成績(jī)</th></tr><tr><td>一班</td><td>30</td><td>89</td><td>一班</td><td>30</td><td>89</td><td>一班</td><td>30</td><td>89</td></tr><tr><td>一班</td><td>30</td><td>89</td><td>一班</td><td>30</td><td>89</td><td>一班</td><td>30</td><td>89</td></tr><tr><td>一班</td><td>30</td><td>89</td><td>一班</td><td>30</td><td>89</td><td>一班</td><td>30</td><td>89</td></tr></tbody></table><p>《俠客行》<br/>年代: 唐 作者: 李白<br/>趙客縵胡纓,吳鉤霜雪明。銀鞍照白馬,颯沓如流星。十步殺一人,千里不留行。事了拂衣去,深藏身與名。閑過信陵飲,脫劍膝前橫。將炙啖朱亥,持觴勸侯嬴。三杯吐然諾,五岳倒為輕。眼花耳熱后,意氣素霓生。救趙揮金槌,邯鄲先震驚。千秋二壯士,煊赫大梁城。縱死俠骨香,不慚世上英。誰能書閤下,白首太玄經(jīng)。</p> </body> </html>PdfUtil.java
public class PdfUtil {/*** @param htmlFile html文件存儲(chǔ)路徑* @param pdfFile 生成的pdf文件存儲(chǔ)路徑* @param chineseFontPath 中文字體存儲(chǔ)路徑*/public static void html2pdf(String htmlFile, String pdfFile, String chineseFontPath){// step 1String url;OutputStream os = null;try {url = new File(htmlFile).toURI().toURL().toString();os = new FileOutputStream(pdfFile);ITextRenderer renderer = new ITextRenderer();renderer.setDocument(url);// 解決中文不顯示問題ITextFontResolver fontResolver = renderer.getFontResolver();fontResolver.addFont(chineseFontPath, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);renderer.layout();renderer.createPDF(os);} catch (Exception e) {} finally {if (os != null) {try {os.close();} catch (Exception e) {e.printStackTrace();}}}}public static void main(String[] args) {try {//獲取項(xiàng)目路徑String projectPath = System.getProperty("user.dir");//html文件路徑String htmlFilePath = projectPath + "/src/main/resources/index.html";// 中文字體存儲(chǔ)路徑String chineseFontPath = projectPath +"/src/main/resources/Fonts/simsun.ttc";// html轉(zhuǎn)pdfhtml2pdf(htmlFilePath, projectPath + "/src/main/resources/html2pdf.pdf", chineseFontPath);System.out.println("轉(zhuǎn)換成功!");} catch (Exception e) {System.out.println("轉(zhuǎn)換失敗!");e.printStackTrace();}} }iText轉(zhuǎn)html為pdf遇到的問題
中文不顯示
原因: iText默認(rèn)不支持中文
解決方法: 引入中文字體 (本機(jī)字體文件庫C:\Windows\Fonts中下載上傳到項(xiàng)目中)
需要注意的是在java代碼中設(shè)置好中文字體后,還需要在html引用該字體,否則不會(huì)起效果。
// 解決中文不顯示問題 ITextFontResolver fontResolver = renderer.getFontResolver(); fontResolver.addFont(chineseFontPath, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED); /*解決html轉(zhuǎn)pdf文件中文不顯示的問題*/ body {font-family: SimSun; }css不起作用
原因: css文件使用的是相對(duì)路徑
解決方法: 將相對(duì)路徑改為絕對(duì)路徑或者把css樣式寫在html內(nèi)部.
html內(nèi)容轉(zhuǎn)為pdf后內(nèi)容不全
解決方法: 在html中設(shè)定紙張大小
/*設(shè)定紙張大小*//* A4紙 *//* @page{size:210mm*297mm} */@page{size:a4}iText轉(zhuǎn)html為pdf遇到的問題
中文不顯示
原因: iText默認(rèn)不支持中文
解決方法: 引入中文字體 (本機(jī)字體文件庫C:\Windows\Fonts中下載上傳到項(xiàng)目中)
需要注意的是在java代碼中設(shè)置好中文字體后,還需要在html引用該字體,否則不會(huì)起效果。
// 解決中文不顯示問題 ITextFontResolver fontResolver = renderer.getFontResolver(); fontResolver.addFont(chineseFontPath, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED); /*解決html轉(zhuǎn)pdf文件中文不顯示的問題*/ body {font-family: SimSun; }css不起作用
原因: css文件使用的是相對(duì)路徑
解決方法: 將相對(duì)路徑改為絕對(duì)路徑或者把css樣式寫在html內(nèi)部.
html內(nèi)容轉(zhuǎn)為pdf后內(nèi)容不全
解決方法: 在html中設(shè)定紙張大小
/*設(shè)定紙張大小*//* A4紙 *//* @page{size:210mm*297mm} */@page{size:a4}推薦博客:https://www.cnblogs.com/julyluo/archive/2012/07/29/2613822.html
推薦博客:https://www.cnblogs.com/liaojie970/p/7132475.html
總結(jié)
以上是生活随笔為你收集整理的java操作pdf之iText快速入门的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 下列字符是c语言保留两位小数,c语言中保
- 下一篇: 机械臂——DH参数