<!-- 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());
}