freemarker ftl模板的使用:批量打印

时间:2024-10-19 11:37:47

freemarker ftl模板的使用:批量打印

Controller代码:

	@GetMapping("/batch-print")
    @Operation(summary = "付款-批量打印")
    public void batchPrint(@Valid PayApplPrintReqVO reqVO, HttpServletResponse response) throws IOException {
        byte[] content = paySipfApplService.batchPrint(reqVO);
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("文件名", "UTF-8"));
        response.setContentType("application/octet-stream");
        // response.setHeader(Header.CONTENT_DISPOSITION.getValue(), PayStrConstants.ATTACHMENT_FILENAME + URLEncoder.encode(PayStrConstants.PAY_APPL_PDF, "UTF-8"));
        // response.setContentType(ContentType.OCTET_STREAM.getValue());
        IoUtil.write(response.getOutputStream(), false, content);
    }

service代码:

	@Override
    public byte[] payApplPrint(List<PayApplPrintRespVO> payApplPrintRespVOList) {
        try {
            if (CollectionUtils.isEmpty(payApplPrintRespVOList)) {
                // 数据不能为空
                throw exception(PayErrorCodeConstants.PAY_SIPF_DATA_NOT_EMPTY_ERROR);
            }

            // 设置数据
            Map<String, Object> map = new HashMap<>();
            map.put("payList", payApplPrintRespVOList);

            // 读取模板
            Template template = configuration.getTemplate("pay_appl.ftl");
            // 生成html
            String htmlContent = FreeMarkerTemplateUtils.processTemplateIntoString(template, map);

            // 生成pfd
            return FileHandleUtils.convertHtmlToPdf(htmlContent);
        } catch (Exception e) {
            log.error("payApplPrint error===========批量打印失败", e);
            throw new ServiceException(500, "批量打印失败:" + e.getMessage());
        }
    }

工具类:

import cn.hutool.core.util.StrUtil;
import com.itextpdf.html2pdf.ConverterProperties;
import com.itextpdf.html2pdf.HtmlConverter;
import com.itextpdf.io.font.PdfEncodings;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.geom.PageSize;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.AreaBreak;
import com.itextpdf.layout.element.IBlockElement;
import com.itextpdf.layout.element.IElement;
import com.itextpdf.layout.font.FontProvider;
import com.itextpdf.layout.property.AreaBreakType;
import org.springframework.core.io.ClassPathResource;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.List;

/**
 * html转换pdf
 */
public class FileHandleUtils {

    private static final String FONT_PATH = "/font/simsun.ttc";

    /**
     * html转换pdf
     *
     * @param htmlContent htmlContent
     * @return 结果
     */
    public static byte[] convertHtmlToPdf(String htmlContent) throws IOException {

        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        PdfWriter pdfWriter = new PdfWriter(outputStream);

        PdfDocument pdfDoc = new PdfDocument(pdfWriter);

        // 设置为 A4 大小 (横版)
        pdfDoc.setDefaultPageSize(PageSize.A4.rotate());

        // 添加中文字体支持
        ConverterProperties properties = new ConverterProperties();
        FontProvider fontProvider = new FontProvider();

        // 添加自定义字体, 例如宋体
        if (StrUtil.isNotBlank(FONT_PATH)) {
            ClassPathResource classPathResource = new ClassPathResource(FONT_PATH);
            String fontPath = classPathResource.getPath() + ",0";
            PdfFont microsoft = PdfFontFactory.createFont(fontPath, PdfEncodings.IDENTITY_H, false);
            fontProvider.addFont(microsoft.getFontProgram(), PdfEncodings.IDENTITY_H);
            properties.setFontProvider(fontProvider);
        }

        Document document = new Document(pdfDoc);
        List<IElement> elements = HtmlConverter.convertToElements(htmlContent, properties);

        int size = elements.size();
        for (int i = 0; i < size; i++) {
            IElement iElement = elements.get(i);
            document.add((IBlockElement) iElement);
            if (!(i == size - 1)) { // 不是最后一页
                // 添加新的一页
                document.add(new AreaBreak(AreaBreakType.NEXT_PAGE));
            }
        }
        document.close();

        pdfDoc.close();
        pdfWriter.close();

        return outputStream.toByteArray();
    }
}

模板pay_appl.ftl

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>PDF Example</title>
    <style>
        body {
            font-family: "宋体";
            font-size: 20px;
        }
        .tab_center_top {
            width: 100%;
        }

        .tab_center td {
            text-align: center;
            height: 30px;
        }

        .div_height {
            /*height: 800px;*/
            margin-left: 100px;
            margin-right: 100px;
        }

        .row_div {
            height: 30px;
        }

        .large-text {
            font-size: 50px;
        }
    </style>
</head>
<body>
    <#list payList as list>
    <!--付款申请单-->
        <div class="div_height">

            <table class="tab_center_top">
                <tr >
                    <th class="large-text" colspan="3">付款申请单</th>
                </tr>

                <tr>
                    <td>单位名称:<#if list.legalOrg??>${list.legalOrg}</#if></td>
                    <td></td>
                    <td>打印日期:<#if list.date??>${list.date}</#if></td>
                </tr>
            </table>


            <table class="tab_center" border="1" cellspacing="0" width="100%" align="center">
                <tr>
                    <th bgcolor="#dcdcdc" colspan="4">付款申请信息</th>
                </tr>

                <tr>
                    <td>申请人</td>
                    <td>申请部门</td>
                    <td>申请货币</td>
                    <td>计划付款日期</td>
                </tr>
                <tr>
                    <td><#if list.applicant??>${list.applicant}</#if></td>
                    <td><#if list.applDeptName??>${list.applDeptName}</#if></td>
                    <td><#if list.currency??>${list.currency}</#if></td>
                    <td><#if list.planPayDate??>${list.planPayDate}</#if></td>
                </tr>
                <tr>
                    <td>付款申请编号</td>
                    <td>付款业务名称</td>
                    <td>申请金额</td>
                    <td>实付金额</td>
                </tr>

                <tr>
                    <td><#if list.payApplNo??>${list.payApplNo}</#if></td>
                    <td><#if list.feeItem??>${list.feeItem}</#if></td>
                    <td><#if list.totalAmount??>${list.totalAmount}</#if></td>
                    <td></td>
                </tr>

                <tr>
                    <td> 收款账户名称</td>
                    <td colspan="3"><#if list.collAccName??>${list.collAccName}</#if></td>
                </tr>

                <tr>
                    <td>收款开户行</td>
                    <td colspan="3"><#if list.collAccOpnBranch??>${list.collAccOpnBranch}</#if></td>
                </tr>

                <tr>
                    <td>收款账号</td>
                    <td colspan="3"><#if list.collAccNo??>${list.collAccNo}</#if></td>
                </tr>

                <tr>
                    <td>支付摘要</td>
                    <td colspan="3"><#if list.paySummary??>${list.paySummary}</#if></td>
                </tr>

                <tr>
                    <td>备注</td>
                    <td colspan="3"><#if list.payApplRemark??>${list.payApplRemark}</#if></td>
                </tr>
            </table>

            <div class="row_div"></div>


                <table class="tab_center" border="1" cellspacing="0" width="100%">
                    <tr  bgcolor="#dcdcdc">
                        <th>任务节点名称</th>
                        <th>节点完成时间</th>
                        <th>节点操作人</th>
                        <th>节点操作</th>
                        <th>节点流转说明</th>
                    </tr>
                    <#if list.historyList??>
                    <#list list.historyList as history>
                        <tr>
                            <td><#if history.taskName??>${history.taskName}</#if></td>
                            <td><#if history.endTimeStr??>${history.endTimeStr}</#if></td>
                            <td><#if history.userName??>${history.userName}</#if></td>
                            <td><#if history.checkType??>${history.checkType}</#if></td>
                            <td><#if history.message??>${history.message}</#if></td>
                        </tr>
                    </#list>
                    </#if>
                </table>
        </div>
    </#list>
</body>
</html>

字体: