java利用freemark和itext出pdf文件

第一步導包

<!--pdf生成工具類-->
	<dependency>
		<groupId>com.itextpdf</groupId>
		<artifactId>itextpdf</artifactId>
		<version>5.4.2</version>
	</dependency>
	<dependency>
		<groupId>com.itextpdf.tool</groupId>
		<artifactId>xmlworker</artifactId>
		<version>5.4.1</version>
	</dependency>
	<dependency>
		<groupId>com.itextpdf</groupId>
		<artifactId>itext-asian</artifactId>
		<version>5.2.0</version>
	</dependency>
	<dependency>
		<groupId>org.freemarker</groupId>
		<artifactId>freemarker</artifactId>
		<version>2.3.29</version>
	</dependency>
	<dependency>
		<groupId>org.xhtmlrenderer</groupId>
		<artifactId>flying-saucer-pdf</artifactId>
		<version>9.1.18</version>
	</dependency>

然後是寫一個 ftl文件,具體寫法請百度,還有font文件,如圖

<!DOCTYPE html>
<html>

	<head>
		<meta charset="utf-8" />
		<title></title>
		<style>
			* {
				margin: 0;
				padding: 0;
				box-sizing: border-box;
			}

			body {
				font-family: SimSun;
			}

			section {
				display: block;
				margin: 20px 10px;
			}

			.title {
				text-align: center;
			}

			.preface p {
				line-height: 30px;
			}

			.preface p.content {
				text-indent: 2em;
			}

			section>table {
				table-layout: fixed;
				width: 100%;
				margin: 20px 0px;
				text-align: center;
				word-wrap: break-word;
			}
		</style>
	</head>

	<body>
		<!-- 標題 start -->
		<section class="title">
			<h2>報價數據</h2>
		</section>
		<!-- 標題 end -->

		<!-- 彙總統計信息 start -->
		<section class="count-info">
			<table border="1" cellspacing="0">
				<#list data as ai>
					<tr>
						<#list ai as ad>
							<#if ad??>
								<#if ad?is_number>
									<td>${ad}</td>
									<#else>
										<#if ad?is_string && ad !="null/null" && ad !="null">
											<td>${ad}</td>
											<#else>
												<td>&nbsp;</td>
										</#if>
								</#if>
								<#else>
									<td>&nbsp;</td>
							</#if>
						</#list>
					</tr>
				</#list>
			</table>
		</section>
	</body>

</html>

在這裏插入圖片描述
然後是controller代碼

@Controller
@RequestMapping("pdf")
public class PdfController extends BaseController {

    @Autowired
    private PdfService pdfService;

    final int interval = -5;

    @RequestMapping("/public/checkData/{orderNum}")
    public void quotationStand(@PathVariable String orderNum) {
        try {
            Map<String, Object> stringObjectMap = pdfService.quotationStand(orderNum);
            System.out.println(stringObjectMap);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @RequestMapping("/public/export/quotationStand/{orderNum}")
    public void quotationStand(@PathVariable String orderNum, HttpServletResponse response) throws Exception {
        ByteArrayOutputStream baos = null;
        OutputStream out = null;
        try {
        // stringObjectMap 是業務邏輯代碼。主要是數據查詢,我就不粘貼出來了
            Map<String, Object> stringObjectMap = pdfService.quotationStand(orderNum);
            baos = PDFTemplateUtil.createPDF(stringObjectMap, "quotationTemplate.ftl");
            // 設置響應消息頭,告訴瀏覽器當前響應是一個下載文件
            //加載示例文檔、
            ByteArrayInputStream swapStream = new ByteArrayInputStream(baos.toByteArray());
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
	            String str = "XXXXXXXX";
            waterMark(swapStream, byteArrayOutputStream, str);
            response.setContentType("application/x-msdownload");
            // 告訴瀏覽器,當前響應數據要求用戶干預保存到文件中,以及文件名是什麼 如果文件名有中文,必須URL編碼
            String fileName = URLEncoder.encode("報價快照.pdf", "UTF-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
            baos = byteArrayOutputStream;
            out = response.getOutputStream();
            baos.writeTo(out);
            baos.close();
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            e.printStackTrace();
            throw new Exception("導出失敗:" + e.getMessage());
        } finally {
            if (baos != null) {
                baos.close();
            }
            if (out != null) {
                out.close();
            }
        }
    }

    /**
     * 加水印
     *
     * @param inputFile
     * @param outputFile
     * @param waterMarkName
     */
    private void waterMark(InputStream inputFile, OutputStream outputFile, String waterMarkName) {
        try {
            PdfReader reader = new PdfReader(inputFile);
            PdfStamper stamper = new PdfStamper(reader, outputFile);

            BaseFont base = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);

            Rectangle pageRect = null;
            PdfGState gs = new PdfGState();
            gs.setFillOpacity(0.2f);
            gs.setStrokeOpacity(0.2f);
            int total = reader.getNumberOfPages() + 1;

            JLabel label = new JLabel();
            FontMetrics metrics;
            int textH = 0;
            int textW = 0;
            label.setText(waterMarkName);
            metrics = label.getFontMetrics(label.getFont());
            textH = metrics.getHeight();
            textW = metrics.stringWidth(label.getText());

            PdfContentByte under;
            for (int i = 1; i < total; i++) {
                pageRect = reader.getPageSizeWithRotation(i);
                under = stamper.getOverContent(i);
                under.saveState();
                under.setGState(gs);
                under.beginText();
                under.setFontAndSize(base, 20);
                // 水印文字成30度角傾斜
                //你可以隨心所欲的改你自己想要的角度
                for (int height = interval + textH; height < pageRect.getHeight();
                     height = height + textH * 10) {
                    for (int width = interval + textW; width < pageRect.getWidth() + textW;
                         width = width + textW * 5) {
                        under.showTextAligned(Element.ALIGN_LEFT
                                , waterMarkName, width - textW,
                                height - textH, 30);
                    }
                }
                // 添加水印文字
                under.endText();
            }
            //說三遍
            //一定不要忘記關閉流
            //一定不要忘記關閉流
            //一定不要忘記關閉流
            stamper.close();
            reader.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

 }

還有service代碼

 package com.ruoyi.portal.util;

import java.io.*;
import java.util.Locale;
import java.util.Map;

import com.itextpdf.text.*;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.tool.xml.XMLWorkerHelper;
import org.springframework.beans.factory.annotation.Value;
import org.xhtmlrenderer.pdf.ITextRenderer;
import com.lowagie.text.pdf.BaseFont;
import freemarker.template.Configuration;
import freemarker.template.Template;

public class PDFTemplateUtil {

    /**
     * 通過模板導出pdf文件
     *
     * @param data             數據
     * @param templateFileName 模板文件名
     * @throws Exception
     */
    public static ByteArrayOutputStream createPDF(Map<String, Object> data, String templateFileName) throws Exception {
        // 創建一個FreeMarker實例, 負責管理FreeMarker模板的Configuration實例
        Configuration cfg = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
        // 指定FreeMarker模板文件的位置
        cfg.setClassForTemplateLoading(PDFTemplateUtil.class, "/templates");
        ITextRenderer renderer = new ITextRenderer();
        OutputStream out = new ByteArrayOutputStream();
        try {
            // 設置 css中 的字體樣式(暫時僅支持宋體和黑體) 必須,不然中文不顯示
            renderer.getFontResolver().addFont("/templates/font/simsun.ttc", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
            // 設置模板的編碼格式
            cfg.setEncoding(Locale.CHINA, "UTF-8");
            // 獲取模板文件
            Template template = cfg.getTemplate(templateFileName, "UTF-8");
            StringWriter writer = new StringWriter();

            // 將數據輸出到html中
            template.process(data, writer);
            writer.flush();

            String html = writer.toString();
            // 把html代碼傳入渲染器中
            renderer.setDocumentFromString(html);

            // 設置模板中的圖片路徑 (這裏的images在resources目錄下) 模板中img標籤src路徑需要相對路徑加圖片名 如<img src="images/xh.jpg"/>
            // String url = PDFTemplateUtil.class.getClassLoader().getResource("/images").toURI().toString();
            String url = "./";
            renderer.getSharedContext().setBaseURL(url);
            renderer.layout();

            renderer.createPDF(out, false);
            renderer.finishPDF();
            out.flush();
            return (ByteArrayOutputStream) out;
        } finally {
            if (out != null) {
                out.close();
            }
        }
    }

    /**
     * 通過模板導出pdf文件
     *
     * @param data             數據
     * @param templateFileName 模板文件名
     * @throws Exception
     */
    public static ByteArrayOutputStream createPDFByByte(Map<String, Object> data, String templateFileName) throws Exception {
        // 創建一個FreeMarker實例, 負責管理FreeMarker模板的Configuration實例
        Configuration cfg = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
        // 指定FreeMarker模板文件的位置
        cfg.setClassForTemplateLoading(PDFTemplateUtil.class, "/templates");
        Document document = new Document(new RectangleReadOnly(824F, 595F));
        OutputStream out = new ByteArrayOutputStream();
        PdfWriter mPdfWriter = PdfWriter.getInstance(document, out);
        document.open();
        try {
            // 設置模板的編碼格式
            cfg.setEncoding(Locale.CHINA, "UTF-8");
            // 獲取模板文件
            Template template = cfg.getTemplate(templateFileName, "UTF-8");
            StringWriter writer = new StringWriter();

            // 將數據輸出到html中
            template.process(data, writer);
            writer.flush();

            String html = writer.toString();
            ByteArrayInputStream bin = new ByteArrayInputStream(html.getBytes());
            XMLWorkerHelper.getInstance().parseXHtml(mPdfWriter, document, bin, null, new ChinaFontProvide());
            document.close();
            return (ByteArrayOutputStream) out;
        } finally {
            if (out != null) {
                out.close();
            }
        }
    }


    public static final class ChinaFontProvide implements FontProvider {

        @Override
        public boolean isRegistered(String s) {
            return false;
        }

        @Override
        public Font getFont(String arg0, String arg1, boolean arg2, float arg3, int arg4, BaseColor arg5) {
            com.itextpdf.text.pdf.BaseFont bfChinese = null;
            try {
                bfChinese = com.itextpdf.text.pdf.BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", com.itextpdf.text.pdf.BaseFont.NOT_EMBEDDED);
            } catch (Exception e) {
                e.printStackTrace();
            }
            Font FontChinese = new Font(bfChinese, 12, Font.NORMAL);
            return FontChinese;
        }
    }

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章