<!-- 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>
import com.itextpdf.text.Anchor;
import com.itextpdf.text.Chunk;
import com.itextpdf.text.Document;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.Image;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.pdf.draw.DottedLineSeparator;
import com.itextpdf.text.pdf.draw.LineSeparator;
import java.io.File;
import java.io.FileOutputStream;
/**
* 生成pdf
* <p>
* 參考: https://blog.csdn.net/weixin_37848710/article/details/89522862?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.nonecase
* https://blog.csdn.net/qq_39207908/article/details/82423388
*/
public class PdfExport {
public static void main(String[] args) {
try {
// document
Document document = new Document(PageSize.A4);
// OutputStream
File file = new File("D:\\Test.pdf");
file.createNewFile();
FileOutputStream fos = new FileOutputStream(file);
PdfWriter writer = PdfWriter.getInstance(document, fos);
// 水印
writer.setPageEvent(new Watermark("HELLO ITEXTPDF"));
// 頁首 和 頁尾
writer.setPageEvent(new MyHeaderFooter());
// 開啟 pdf
document.open();
/** 向 pdf 中寫入內容 *** start ******************************************************/
// 1. 段落
Paragraph paragraph_1 = new Paragraph("HELLO PDF!", titlefont);
// 文字位置(靠左,居中,靠右 等)
paragraph_1.setAlignment(Element.ALIGN_CENTER);
// 左縮排
paragraph_1.setIndentationLeft(12);
// 右縮排
paragraph_1.setIndentationRight(12);
// 首行縮排
paragraph_1.setFirstLineIndent(24);
// 行間距
paragraph_1.setLeading(20f);
// 段落上空白
paragraph_1.setSpacingBefore(5f);
// 段落下空白
paragraph_1.setSpacingAfter(10f);
// 2. 直線
Paragraph paragraph_2 = new Paragraph();
paragraph_2.add(new Chunk(new LineSeparator()));
// 3. 點線
Paragraph paragraph_3 = new Paragraph();
paragraph_3.add(new Chunk(new DottedLineSeparator()));
// 4. 超連結
Anchor link = new Anchor("baidu");
link.setReference("www.baidu.com");
// 5. 定位,如: 跳轉到文件頭部位置(測試發現: 使用瀏覽器時可以正常跳轉,使用 wps 時不可以)
Anchor goTop = new Anchor("goTop");
goTop.setReference("#top");
// 6. 圖片(圖片地址若是以 http 開頭而非 https 開頭,可能會報錯)
Image image = Image.getInstance("https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=1200524016,3386333024&fm=26&gp=0.jpg");
image.setAlignment(Image.ALIGN_CENTER);
image.scalePercent(40);
// 表格
PdfPTable table_1 = createTable(new float[]{50, 50});
table_1.addCell(createCell("TEST", textfont, Element.ALIGN_LEFT));
table_1.addCell(createCell("TEST", textfont, Element.ALIGN_LEFT));
table_1.addCell(createCell("測試", textfont, Element.ALIGN_LEFT));
table_1.addCell(createCell("測試", textfont, Element.ALIGN_LEFT));
PdfPTable table_2 = createTable(new float[]{100});
table_2.addCell(createCell("TEST", textfont, Element.ALIGN_LEFT));
table_2.addCell(createCell("測試", textfont, Element.ALIGN_LEFT));
// 直線
Paragraph paragraph_4 = new Paragraph();
paragraph_4.add(new Chunk(new LineSeparator()));
// 行間距
paragraph_4.setLeading(20f);
// 段落上空白
paragraph_4.setSpacingBefore(50f);
// 段落下空白
paragraph_4.setSpacingAfter(50f);
// 合併單元格
PdfPTable table_3 = createTable(new float[]{50, 50, 50, 50});
table_3.addCell(createCellWithSpan("HEAD", textfont, Element.ALIGN_CENTER, 1, 4));
table_3.addCell(createCell("AA", textfont, Element.ALIGN_LEFT));
table_3.addCell(createCell("AA", textfont, Element.ALIGN_LEFT));
table_3.addCell(createCell("AA", textfont, Element.ALIGN_LEFT));
table_3.addCell(createCell("AA", textfont, Element.ALIGN_LEFT));
table_3.addCell(createCellWithSpan("SPAN", textfont, Element.ALIGN_LEFT, 2, 2));
table_3.addCell(createCell("BB", textfont, Element.ALIGN_LEFT));
table_3.addCell(createCell("BB", textfont, Element.ALIGN_LEFT));
table_3.addCell(createCell("CC", textfont, Element.ALIGN_LEFT));
table_3.addCell(createCell("CC", textfont, Element.ALIGN_LEFT));
table_3.addCell(createCell("EE", textfont, Element.ALIGN_LEFT));
table_3.addCell(createCell("EE", textfont, Element.ALIGN_LEFT));
table_3.addCell(createCell("EE", textfont, Element.ALIGN_LEFT));
table_3.addCell(createCell("EE", textfont, Element.ALIGN_LEFT));
table_3.addCell(createCell("FF", textfont, Element.ALIGN_LEFT));
table_3.addCell(createCellForImage(image, textfont, Element.ALIGN_LEFT, 2, 2));
table_3.addCell(createCell("FF", textfont, Element.ALIGN_LEFT));
table_3.addCell(createCell("GG", textfont, Element.ALIGN_LEFT));
table_3.addCell(createCell("GG", textfont, Element.ALIGN_LEFT));
// 補充: table.setHeaderRows(2); 指定前 2 行作為標題行,作用: 使得當 table 由於分頁被分割時,可以在每頁都顯示標題行
document.add(paragraph_1);
document.add(paragraph_2);
document.add(paragraph_3);
document.add(link);
document.add(image);
document.add(table_1);
document.add(table_2);
document.add(paragraph_4);
document.add(table_3);
document.add(goTop);
/** 向 pdf 中寫入內容 *** end ******************************************************/
// 關閉 pdf
document.close();
} catch (Exception e) {
e.printStackTrace();
}
}
// 定義全域性的字型靜態變數
private static Font titlefont;
private static Font headfont;
private static Font keyfont;
private static Font textfont;
// 最大寬度
private static int maxWidth = 520;
// 字型
static {
try {
BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
titlefont = new Font(bfChinese, 16, Font.BOLD);
headfont = new Font(bfChinese, 14, Font.BOLD);
keyfont = new Font(bfChinese, 10, Font.BOLD);
textfont = new Font(bfChinese, 10, Font.NORMAL);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 建立指定 列寬、列數 的表格
*
* @param widths (列數: 陣列元素的個數)
* @return
*/
public static PdfPTable createTable(float[] widths) {
PdfPTable table = new PdfPTable(widths);
try {
table.setTotalWidth(maxWidth);
table.setLockedWidth(true);
table.setHorizontalAlignment(Element.ALIGN_CENTER);
table.getDefaultCell().setBorder(1);
} catch (Exception e) {
e.printStackTrace();
}
return table;
}
/**
* 建立單元格
*
* @param value 值
* @param font 字型
* @param horizontalAlignment 水平位置
* @return
*/
public static PdfPCell createCell(String value, Font font, int horizontalAlignment) {
PdfPCell cell = new PdfPCell();
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
cell.setHorizontalAlignment(horizontalAlignment);
// 建議不設定單元格固定高度,因為這會導致單元格中的內容超出單元格的所能容納的字數時,使得部分內容丟失
//cell.setFixedHeight(30);
cell.setPhrase(new Phrase(value, font));
return cell;
}
/**
* 建立單元格
*
* @param value 值
* @param font 字型
* @param horizontalAlignment 水平位置
* @param rowspan 合併行數
* @param colspan 合併列數
* @return
*/
public static PdfPCell createCellWithSpan(String value, Font font, int horizontalAlignment, int rowspan, int colspan) {
PdfPCell cell = new PdfPCell();
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
cell.setHorizontalAlignment(horizontalAlignment);
cell.setRowspan(rowspan);
cell.setColspan(colspan);
cell.setPhrase(new Phrase(value, font));
return cell;
}
/**
* 建立單元格(含圖片)
*
* @param image
* @param font
* @param horizontalAlignment
* @param colspan
* @param rowspan
* @return
*/
public static PdfPCell createCellForImage(Image image, Font font, int horizontalAlignment, int colspan, int rowspan) {
PdfPCell cell = new PdfPCell();
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
cell.setHorizontalAlignment(horizontalAlignment);
cell.setColspan(colspan);
cell.setRowspan(rowspan);
cell.setImage(image);
return cell;
}
}
點選檢視程式碼
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import java.io.IOException;
public class MyHeaderFooter extends PdfPageEventHelper {
/**
* 總頁數
*/
PdfTemplate totalPage;
Font hfFont;
{
try {
hfFont = new Font(BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED), 8, Font.NORMAL);
} catch (DocumentException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 開啟文件時,建立一個總頁數的模版
*/
@Override
public void onOpenDocument(PdfWriter writer, Document document) {
PdfContentByte cb = writer.getDirectContent();
totalPage = cb.createTemplate(30, 15);
}
/**
* 一頁載入完成觸發,寫入頁首或頁尾
*/
@Override
public void onEndPage(PdfWriter writer, Document document) {
PdfPTable table = new PdfPTable(2);
try {
table.setTotalWidth(PageSize.A4.getWidth());
table.setWidths(new int[]{(int) (PageSize.A4.getWidth() / 2), (int) (PageSize.A4.getWidth() / 2)});
table.setLockedWidth(true);
// 第幾頁
PdfPCell cell_1 = new PdfPCell(new Paragraph("第" + writer.getPageNumber() + "頁/", hfFont));
cell_1.setHorizontalAlignment(Element.ALIGN_RIGHT);
cell_1.setBorder(Rectangle.NO_BORDER);
table.addCell(cell_1);
// 總頁數
PdfPCell cell_2 = new PdfPCell(Image.getInstance(totalPage));
cell_2.setBorder(Rectangle.NO_BORDER);
table.addCell(cell_2);
// 將 頁首/頁尾 寫到指定位置,指定到上面就是頁首,指定到下面就是頁尾
table.writeSelectedRows(0, -1, 0, 20, writer.getDirectContent());
} catch (Exception de) {
throw new ExceptionConverter(de);
}
}
/**
* 全部完成後,將總頁數的 pdf 模版寫到指定位置
*/
@Override
public void onCloseDocument(PdfWriter writer, Document document) {
String text = "總" + (writer.getPageNumber()) + "頁";
ColumnText.showTextAligned(totalPage, Element.ALIGN_LEFT, new Paragraph(text, hfFont), 0, 5, 0);
}
}
點選檢視程式碼
import com.itextpdf.text.Document;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.PdfWriter;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
/**
* pdf 下載
*/
@Controller
public class PdfController {
@GetMapping("/downloadPdf")
public void downloadPdf(HttpServletResponse response) {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Document document = new Document(PageSize.A4);
PdfWriter.getInstance(document, baos);
// 開啟 pdf
document.open();
// 向 pdf 寫入內容
Paragraph paragraph = new Paragraph("hello world");
document.add(paragraph);
// 關閉 pdf
document.close();
String fileName = "MyPdfTest";
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "attachment; filename=" + fileName + ".pdf");
response.setContentLength(baos.size());
OutputStream out = response.getOutputStream();
baos.writeTo(out);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
點選檢視程式碼
^
|
|
Y
|
+----------+
| |
| pdf |
| |
| 文 件 |
| |
| |
---+----------+----X-->
O|
|
|
// 測試
public static void main(String[] args) {
Document document = new Document(PageSize.A4);
System.err.println("rectangle:" + document.getPageSize());
// 頂部 y 座標
System.err.println("top:" + document.getPageSize().getTop());
// 底部 y 座標
System.err.println("bottom:" + document.getPageSize().getBottom());
// 最左側 x 座標
System.err.println("left:" + document.getPageSize().getLeft());
// 最右側 x 座標
System.err.println("right:" + document.getPageSize().getRight());
}