相关推荐recommended
springboot 动态导出pdf
作者:mmseoamin日期:2024-02-28

springboot 动态导出pdf

原理是通过freemarker插入数据到html模版里面,html你就叫前端帮你写好,他不写你就告诉你主管让他叫他写,你只管往预留的位置插入数据就行,然后通过itextpdf会将准备好html文件转成PDF。

1、准备依赖

        
        
            com.itextpdf
            html2pdf
            4.0.3
        
        
        
            org.freemarker
            freemarker
            2.3.30
        
        

2、准备html模版



    
    


springboot 动态导出pdf,第1张
WhiteCoat Holdings Pte Ltd.
Clinic Licence No.: 18M0119/01/182
201 Henderson Road #05-11/12
Apex @ Henderson
Singapore 159545
GST Reg. No: 201610235E
T: +65 6909 6909
F: +65 6909 6909
E: contactus@whitecoat.com.sg
whitecoat.com.sg
Name:
${data.name!}

NRIC/FIN/Passport No:
${data.idNo!}
Invoice No.:
${data.invoiceNo!}

Invoice Date:
${data.invoiceDateStr!}

This is a computer generated invoice. No signature is required.
S/N Description Amount
1 Medication
<#list data.medicationList as item> ${item.productName!}

Subtotal
Quantity
<#list data.medicationList as item> ${item.quantity!}

Subtotal

<#list data.medicationList as item> $${item.amount!}

${data.subtotal!}
2 Administrative charges $${data.adminCharge!}
Subtotal(Excluding GST) $${data.subtotalExcludingGST!}
GST(${data.tax!}%) $${data.GST!}
Total(Including GST) $${data.totalIncludingGST!}
Bank remittance details for payment by Bank Telegraphic
Transfer in Singapore Dollars to:
Name of Bank: United Overseas Bank Ltd. Holland Branch
Account Name: Whitecoat Holdings Pte Ltd.
Account No: 341-308-316-6
Bank Code: 7375
Branch Code: 020
Bank Swift Code: UOVBSGSG

3、下载代码

    @ApiOperation(value = "下载pdf")
    @GetMapping("downloadPDF/staffPurchase")
    public ResponseResult download(String id, HttpServletResponse response) throws Exception {
        StaffPurchasePDFVo data = staffPurchaseMapper.getStaffPurchasePDFData(id);
        HashMap mapData = Maps.newHashMap();
        mapData.put("data", data);
        long timeMillis = System.currentTimeMillis();
        String templateContent = HtmlUtils.getTemplateContent("Staff_Purchase_Receipt.ftl", mapData);
        HtmlUtils.html2Pdf(response, templateContent, timeMillis + "");
        return ResponseResult.success();
    }

4、htmlutils代码

import com.itextpdf.html2pdf.ConverterProperties;
import com.itextpdf.html2pdf.HtmlConverter;
import com.itextpdf.layout.font.FontProvider;
import freemarker.template.Configuration;
import freemarker.template.Template;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Map;
import java.util.Objects;
@Slf4j
public class HtmlUtils {
    /**
     * @return
     * @throws Exception
     */
    public static String getTemplateDirectory() {
        ClassLoader classLoader = HtmlUtils.class.getClassLoader();
        URL resource = classLoader.getResource("templates");
        try {
            return Objects.requireNonNull(resource).toURI().getPath();
        } catch (URISyntaxException e) {
            log.error("获取模板文件夹失败,{}", e);
        }
        return null;
    }
    /**
     * 获取模板内容
     *
     * @param templateName 模板文件名
     * @param paramMap     模板参数
     * @return
     * @throws Exception
     */
    public static String getTemplateContent(String templateName, Map paramMap) throws Exception {
        Configuration config = ApplicationContextUtil.getBean(FreeMarkerConfigurer.class).getConfiguration();
        config.setDefaultEncoding("UTF-8");
        Template template = config.getTemplate(templateName, "UTF-8");
        return FreeMarkerTemplateUtils.processTemplateIntoString(template, paramMap);
    }
    /**
     * HTML 转 PDF
     *
     * @param content html内容
     * @param outPath 输出pdf路径
     * @return 是否创建成功
     */
    public static boolean html2Pdf(String content, String outPath) {
        try {
            ConverterProperties converterProperties = new ConverterProperties();
            converterProperties.setCharset("UTF-8");
            FontProvider fontProvider = new FontProvider();
            fontProvider.addSystemFonts();
            converterProperties.setFontProvider(fontProvider);
            HtmlConverter.convertToPdf(content, new FileOutputStream(outPath), converterProperties);
        } catch (Exception e) {
            log.error("生成模板内容失败,{}", e);
            return false;
        }
        return true;
    }
    /**
     * HTML 转 PDF
     *
     * @param content html内容
     * @return PDF字节数组
     */
    public static void html2Pdf(HttpServletResponse response, String content,String filename) throws IOException {
        response.setHeader("Content-Type", "application/octet-stream");
        response.setCharacterEncoding("utf-8");
        response.setHeader("Content-Disposition", "attachment;filename="+filename+".pdf");
        try (ServletOutputStream outputStream = response.getOutputStream()) {
            ConverterProperties converterProperties = new ConverterProperties();
            converterProperties.setCharset("UTF-8");
            FontProvider fontProvider = new FontProvider();
            fontProvider.addSystemFonts();
            converterProperties.setFontProvider(fontProvider);
            HtmlConverter.convertToPdf(content, outputStream, converterProperties);
        } catch (Exception e) {
            log.error("生成 PDF 失败,{}", e);
        }
    }
} 

ApplicationContextUtil代码、

import org.springframework.beans.BeansException;
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Configuration;
@Configuration
@AutoConfigureOrder(-1)
public class ApplicationContextUtil implements ApplicationContextAware {
    private static ApplicationContext applicationContext = null;
    public static Object getBeanByName(String beanName) {
        if (applicationContext == null) {
            return null;
        }
        return applicationContext.getBean(beanName);
    }
    public static  T getBean(Class type) {
        return applicationContext.getBean(type);
    }
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        ApplicationContextUtil.applicationContext = applicationContext;
    }
}

5、freemarker的基本语法

https://developer.aliyun.com/article/942606

6、注意

如果css写了具体的大小比如width: 21cm;,那么下载出来的pdf会因为超出边界被截取,别写。