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-08Springboot項(xiàng)目引入druid安裝部署使用教程
這篇文章主要介紹了Springboot項(xiàng)目引入druid安裝部署使用,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-01-01Java 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-12mybatis 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-10idea批量啟動(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