java導(dǎo)出pdf文件的詳細(xì)實(shí)現(xiàn)方法
使用注意點(diǎn)
因?yàn)樵瓉碇谱鞯膒df表單內(nèi)容過于復(fù)雜,下面代碼只包含前兩行的操作。
本次操作需要前端向后端發(fā)起請(qǐng)求,后端返回?cái)?shù)據(jù)給前端用于下載,所以沒有在本地進(jìn)行保存。
第 1 步制作pdf模板需要的pdf編輯軟件基本上都需要錢,可以去買一個(gè)
第 2 步獲取的pdf導(dǎo)出的中文需要的文件,如果pdf輸出的內(nèi)容有中文就需要去弄一下這個(gè)文件,在代碼中用于讀取設(shè)置中文字體
包含內(nèi)容
1、導(dǎo)出pdf
2、設(shè)置斜體水印
1、制作pdf模板
先將需要的pdf模板通過word制作出來,然后導(dǎo)出為pdf

使用Adobe Acrobat DC 打開并制作模板(其他pdf編輯軟件也可以)

選擇打開前面導(dǎo)出的pdf模板

點(diǎn)擊準(zhǔn)備表單

點(diǎn)擊之后,可以針對(duì)沒一個(gè)位置進(jìn)行編輯,選中雙擊就可以進(jìn)行編輯了,要注意,每個(gè)位置的名字都需要是唯一的

全部賦值后保存即可
2、獲取pdf導(dǎo)出中文需要的文件
獲取中文字體需要的文件

在電腦這個(gè)路徑下選擇下載一個(gè)就行

3、實(shí)現(xiàn)
pom依賴
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext7-core</artifactId>
<version>7.2.3</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>2.0.24</version>
</dependency>
controller接口
@GetMapping("/exportPDF/{applyId}")
public ResponseEntity<byte[]> exportPDF(@PathVariable("applyId") String applyId, HttpServletResponse response) throws IOException,ParseException,Exception {
byte[] res = applyService.exportPDF(applyId);
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Disposition", "attachment; filename=filled_form.pdf");
headers.add("Content-Type", "application/pdf");
return ResponseEntity.ok()
.headers(headers)
.body(res);
}service具體實(shí)現(xiàn)
public static byte[] exportPDF1() throws Exception {
String inputTemplateName = "template";
try {
pdfBytes = null;
Map<String, String> map = new HashMap<>();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
// map預(yù)填數(shù)據(jù),用于后面讀取輸出到pdf文件上
map.put("department-1", "研發(fā)中心");
map.put("submitDate-1", sdf.format(new Date()));
map.put("submitPerson-1", "張三");
map.put("travelPerson-1", "李四");
map.put("receivePerson-1","王五");
// 設(shè)置中文字體
PdfFont chineseFont = PdfFontFactory.createFont("src/main/resources/file/simsun.ttc,0");
// 模板路徑
String templatePath = "src\\main\\resources\\file\\" + inputTemplateName + ".pdf";
// 重點(diǎn),這一個(gè)關(guān)聯(lián)了reader 和 writer
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
// 讀取文件
FileInputStream pdfInputStream = new FileInputStream(new File(templatePath));
// 定義 reader 和writer
PdfReader reader = new PdfReader(pdfInputStream);
PdfWriter writer = new PdfWriter(byteArrayOutputStream,new WriterProperties().setStandardEncryption(
null,
null,
EncryptionConstants.ALLOW_PRINTING, // 允許打印
EncryptionConstants.ENCRYPTION_AES_128 // 加密方式
));
// 根據(jù) reader 和writer 創(chuàng)建 PdfDocument
PdfDocument pdfDocument = new PdfDocument(reader,writer);
// 下面是給文件添加水印,不需要的可以直接刪掉
// 獲取 pdf 模板頁數(shù)
int numberOfPages = pdfDocument.getNumberOfPages();
// 遍歷每一頁并添加水印
for (int i = 1; i <= numberOfPages; i++) {
PdfPage page = pdfDocument.getPage(i);
// 獲取頁面尺寸(在這里我沒有用)
int pageWidth = (int) Math.floor(page.getPageSize().getWidth());
int pageHeight = (int) Math.floor(page.getPageSize().getHeight());
// 創(chuàng)建一個(gè) PdfCanvas 對(duì)象
PdfCanvas canvas = new PdfCanvas(page);
// 保存當(dāng)前坐標(biāo)系狀態(tài)
canvas.saveState();
// 水印內(nèi)容旋轉(zhuǎn)
double angle = Math.toRadians(45);
double cos = Math.cos(angle);
double sin = Math.sin(angle);
canvas.concatMatrix(cos, sin, -sin, cos, 0, 0);
// 設(shè)置水印的字體和透明度
canvas.setFontAndSize(PdfFontFactory.createFont(), 20);
canvas.setFillColorRgb(0.75f, 0.75f, 0.75f); // 灰色
canvas.setLineWidth(2);
// 正常應(yīng)該根據(jù)獲取到的頁面尺寸進(jìn)行 x y 軸的遍歷并
// 但是我這邊沒有鋪滿,就自己設(shè)置了遍歷的范圍
for (int x = -90; x < 2000; x += 300) {
for (int y = -190; y < 2000; y += 200) {
// 繪制水印文字
canvas.beginText();
canvas.setTextMatrix(x, y); // 設(shè)置水印位置
canvas.showText("Watermark Text this is just a test"); // 水印文字內(nèi)容
canvas.endText();
}
}
// 恢復(fù)坐標(biāo)系狀態(tài)
canvas.restoreState();
}
// form 可以理解為把pdf文件看做一個(gè)form表單,以key value鍵值對(duì)保存
PdfAcroForm form = PdfAcroForm.getAcroForm(pdfDocument, true);
// 遍歷上面預(yù)填的 map 并將值根據(jù) key 賦值到form
for (Map.Entry<String, String> entry : map.entrySet()) {
form.getField(entry.getKey()).setValue(entry.getValue());
form.getField(entry.getKey()).setFont(chineseFont).setFontSize(8);
}
pdfDocument.close();
// 返回文件流
pdfBytes = byteArrayOutputStream.toByteArray();
return pdfBytes;
} catch (Exception e) {
e.printStackTrace();
}finally {
return pdfBytes;
}
}
4、前端發(fā)起請(qǐng)求并生成下載鏈接
exportPdf(applyId) {
exportPDF(applyId).then(res => {
// 創(chuàng)建一個(gè) Blob 對(duì)象,指定類型為 PDF 文件
const blob = new Blob([res.data], { type: 'application/pdf' });
// 創(chuàng)建一個(gè) URL 對(duì)象,指向 Blob 數(shù)據(jù)
const url = URL.createObjectURL(blob);
// 創(chuàng)建一個(gè)下載鏈接
const link = document.createElement('a');
link.href = url;
link.download = 'generated_with_form.pdf'; // 設(shè)置下載文件名
// 模擬點(diǎn)擊下載鏈接
link.click();
// 下載完成后釋放 URL 對(duì)象
URL.revokeObjectURL(url);
})
},總結(jié)
到此這篇關(guān)于java導(dǎo)出pdf文件的詳細(xì)實(shí)現(xiàn)方法的文章就介紹到這了,更多相關(guān)java導(dǎo)出pdf文件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring Boot快速實(shí)現(xiàn) IP地址解析的示例詳解
這篇文章主要介紹了Spring Boot快速實(shí)現(xiàn)IP地址解析,本文通過示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-08-08
Springboot項(xiàng)目引入druid安裝部署使用教程
這篇文章主要介紹了Springboot項(xiàng)目引入druid安裝部署使用,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-01-01
Java UrlRewriter偽靜態(tài)技術(shù)運(yùn)用深入分析
通常我們?yōu)榱烁玫木徑夥?wù)器壓力,和增強(qiáng)搜索引擎的友好面,都將文章內(nèi)容生成靜態(tài)頁面,這就產(chǎn)生了偽靜態(tài)技術(shù),也就是我們常說的Url Rewriter重寫技術(shù)2012-12-12
mybatis resultType自帶數(shù)據(jù)類型別名解讀
MyBatis為了簡(jiǎn)化開發(fā),通過org.apache.ibatis.type.TypeAliasRegistry為常見類定義了別名,這些別名包括基本數(shù)據(jù)類型及其數(shù)組、集合類型等,如string對(duì)應(yīng)java.lang.String,int對(duì)應(yīng)java.lang.Integer等,此外,還有特殊前綴的別名如_int對(duì)應(yīng)int類型2024-10-10
idea批量啟動(dòng)多個(gè)微服務(wù)具體實(shí)現(xiàn)
這篇文章主要給大家介紹了關(guān)于idea批量啟動(dòng)多個(gè)微服務(wù)的具體實(shí)現(xiàn),在微服務(wù)開發(fā)過程中,我們經(jīng)常要在本地啟動(dòng)很多個(gè)微服務(wù),文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下2023-07-07

