最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot手把手實(shí)現(xiàn)生成PDF功能的示例代碼

 更新時(shí)間:2025年12月01日 09:25:06   作者:眾納  
這篇文章主要介紹了如何使用Thymeleaf模板和iText庫配合Flying-pdf工具,實(shí)現(xiàn)在業(yè)務(wù)系統(tǒng)中生成PDF文件的功能,感興趣的小伙伴可以了解下

本文介紹了如何使用Thymeleaf模板和iText庫配合Flying-pdf工具,實(shí)現(xiàn)在業(yè)務(wù)系統(tǒng)中生成PDF文件的功能,以訂單和發(fā)貨單為例,詳細(xì)講解了字體配置、Maven依賴、工具類實(shí)現(xiàn)和控制層方法。

需求:

在開發(fā)的業(yè)務(wù)系統(tǒng)中我希望能有一個(gè)轉(zhuǎn)出PDF功能。比如:轉(zhuǎn)出訂單,轉(zhuǎn)出發(fā)貨單等

原理:

使用itext 與flying-pdf 對(duì) thymeleaf 模板填充后生成PDF

實(shí)現(xiàn):

1.準(zhǔn)備中文字體,用于PDF中關(guān)于中文文字的顯示。

存放位置

2.Maven 主要依賴

<!--itext 生成PDF-->
<dependency>
    <groupId>com.lowagie</groupId>
    <artifactId>itext</artifactId>
    <version>${itext.version}</version>
</dependency>

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>3.9</version>
</dependency>
<!--xlsx(07)-->
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>3.9</version>
</dependency>

<dependency>
    <groupId>org.xhtmlrenderer</groupId>
    <artifactId>flying-saucer-pdf</artifactId>
    <version>9.1.9</version>
</dependency>

3.工具類

import com.lowagie.text.pdf.BaseFont;
import com.lowagie.text.xml.xmp.XmpWriter;
import lombok.extern.slf4j.Slf4j;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import org.w3c.dom.Document;
import org.xhtmlrenderer.pdf.ITextFontResolver;
import org.xhtmlrenderer.pdf.ITextRenderer;


import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.*;
import java.util.List;
import java.util.Map;

/**
 * pdf處理工具類
 *
 */
@Slf4j
public class PdfUtil {

    /**
     * 以文件流形式下載到瀏覽器
     *
     * @param templateEngine   配置
     * @param templateName 模板名稱
     * @param listVars     模板參數(shù)集
     * @param response     HttpServletResponse
     * @param fileName     下載文件名稱
     */
    public static void download(TemplateEngine templateEngine, String templateName, List<Map<String, Object>> listVars, HttpServletResponse response, String fileName) {
        // 設(shè)置編碼、文件ContentType類型、文件頭、下載文件名
        response.setCharacterEncoding(XmpWriter.UTF8);
        response.setContentType("application/pdf");
        try {
            response.setHeader("Content-Disposition", "attachment;fileName=" +
                    new String(fileName.getBytes("gb2312"), "ISO8859-1"));
        } catch (UnsupportedEncodingException e) {
            log.error(e.getMessage(), e);
        }
        try (ServletOutputStream out = response.getOutputStream()) {
            generateAll(templateEngine, templateName, out, listVars);
            out.flush();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }

    /**
     * pdf下載到特定位置
     *
     * @param templateEngine   配置
     * @param templateName 模板名稱
     * @param listVars     模板參數(shù)集
     * @param filePath     下載文件路徑
     */
    public static void save(TemplateEngine templateEngine, String templateName, List<Map<String, Object>> listVars, String filePath) {
        try (OutputStream out = new FileOutputStream(filePath);) {
            generateAll(templateEngine, templateName, out, listVars);
            out.flush();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }

    /**
     * pdf預(yù)覽
     *
     * @param templateEngine   配置
     * @param templateName 模板名稱
     * @param listVars     模板參數(shù)集
     * @param response     HttpServletResponse
     */
    public static void preview(TemplateEngine templateEngine, String templateName, List<Map<String, Object>> listVars, HttpServletResponse response) {
        try (ServletOutputStream out = response.getOutputStream()) {
            generateAll(templateEngine, templateName, out, listVars);
            out.flush();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }

    /**
     * 按模板和參數(shù)生成html字符串,再轉(zhuǎn)換為flying-saucer識(shí)別的Document
     *
     * @param templateName 模板名稱
     * @param variables   模板參數(shù)
     * @return Document
     */
    private static Document generateDoc(TemplateEngine templateEngine, String templateName, Map<String, Object> variables)  {
        // 聲明一個(gè)上下文對(duì)象,里面放入要存到模板里面的數(shù)據(jù)
        final Context context = new Context();
        context.setVariables(variables);
        StringWriter stringWriter = new StringWriter();
        try(BufferedWriter writer = new BufferedWriter(stringWriter)) {
            templateEngine.process(templateName,context, writer);
            writer.flush();
            DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
            return builder.parse(new ByteArrayInputStream(stringWriter.toString().getBytes()));
        }catch (Exception e){
            //ResponseEnum.TEMPLATE_PARSE_ERROR.assertFail(e);
        }
        return null;
    }

    /**
     * 核心: 根據(jù)Thymeleaf 模板生成pdf文檔
     *
     * @param templateEngine 配置
     * @param templateName 模板名稱
     * @param out          輸出流
     * @param listVars     模板參數(shù)
     * @throws Exception 模板無法找到、模板語法錯(cuò)誤、IO異常
     */
    private static void generateAll(TemplateEngine templateEngine, String templateName, OutputStream out, List<Map<String, Object>> listVars) throws Exception {
        // 斷言參數(shù)不為空
        //ResponseEnum.TEMPLATE_DATA_NULL.assertNotEmpty(listVars);
        ITextRenderer renderer = new ITextRenderer();
        //設(shè)置字符集(宋體),此處必須與模板中的<body style="font-family: SimSun">一致,區(qū)分大小寫,不能寫成漢字"宋體"
        ITextFontResolver fontResolver = renderer.getFontResolver();
        //避免中文為空設(shè)置系統(tǒng)字體
        fontResolver.addFont("static/fonts/simsun.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
        // 如果linux下有問題,可使用以下方式解決。
        // 有一個(gè)項(xiàng)目是用docker部署的,一直報(bào)錯(cuò)找不到simsun.ttf文件,但需要將simsun.ttf上傳到/usr/share/fonts
        //fontResolver.addFont(CommonUtil.isLinux() ? "/usr/share/fonts/simsun.ttf" : "static/fonts/simsun.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);

        //根據(jù)參數(shù)集個(gè)數(shù)循環(huán)調(diào)用模板,追加到同一個(gè)pdf文檔中
        //(注意:此處從1開始,因?yàn)榈?是創(chuàng)建pdf,從1往后則向pdf中追加內(nèi)容)
        for (int i = 0; i < listVars.size(); i++) {
            Document docAppend = generateDoc(templateEngine, templateName, listVars.get(i));
            renderer.setDocument(docAppend, null);
            //展現(xiàn)和輸出pdf
            renderer.layout();
            if(i==0){
                renderer.createPDF(out, false);
            }else {
                //寫下一個(gè)pdf頁面
                renderer.writeNextDocument();
            }

        }
        renderer.finishPDF(); //完成pdf寫入
    }
}

4.控制層方法 (原理是把對(duì)象傳過去,由thymeleaf解析)

import com.flo.po.Dto.OrderDetailedDto;
import com.flo.po.Dto.OrderDto;
import com.flo.service.OrderDetailedService;
import com.flo.service.OrderService;
import com.flo.util.PdfUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.thymeleaf.TemplateEngine;

import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 文檔預(yù)覽、下載
 *
 */
@RestController
@RequestMapping(value = "/document")
@Api(tags = "文檔預(yù)覽、下載API")
public class DocumentController {

    @Autowired
    private TemplateEngine templateEngine;


    @Autowired
    private OrderService orderService;//訂單表頭

    @Autowired
    private OrderDetailedService orderDetailedService;//訂單表身

    /**
     * pdf預(yù)覽
     * @param response HttpServletResponse
     */
    @GetMapping(value = "/pdf/preview")
    @ApiOperation(value="pdf預(yù)覽")
    public void preview(HttpServletResponse response,Integer id) {

        OrderDto orderDto=orderService.findById(id);
        List<OrderDetailedDto> list=orderDetailedService.findAll(new OrderDetailedDto(){{setOrderId(id);}});

        // 構(gòu)造freemarker模板引擎參數(shù),listVars.size()個(gè)數(shù)對(duì)應(yīng)pdf頁數(shù)
        List<Map<String,Object>> listVars = new ArrayList<>();
        Map<String,Object> variables = new HashMap<>(4);
        variables.put("title","訂單明細(xì)");
        variables.put("custName",orderDto.getCustomName());
        variables.put("adr",orderDto.getAddress());
        variables.put("tel",orderDto.getTel());
        variables.put("list",list);
        listVars.add(variables);
        PdfUtil.preview(templateEngine,"pdfPage",listVars,response);
    }
}

5.PDF模板(pdfPage.html)

注意事項(xiàng):

1.盡可能把CSS樣式放在這個(gè)模板里,外部引入可能會(huì)存在一些問題。

2.關(guān)于圖片,切記一定要給完整路徑,而非相對(duì)路徑。如./uploadFile/logo.png 需要加上http://地址/uploadFile/logo.png

3.圖片名稱不能包含中文,否則會(huì)找不到路徑(是由于編碼為UTF8的原因)

位置

        

效果:

到此這篇關(guān)于SpringBoot手把手實(shí)現(xiàn)生成PDF功能的示例代碼的文章就介紹到這了,更多相關(guān)SpringBoot PDF內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

巴楚县| 丹江口市| 拜城县| 龙山县| 临武县| 鹿邑县| 株洲县| 海南省| 安福县| 大荔县| 岑溪市| 东丰县| 宁河县| 马山县| 黔南| 宝应县| 渝中区| 外汇| 资源县| 嘉黎县| 崇州市| 海兴县| 镶黄旗| 桂平市| 内乡县| 南江县| 保靖县| 防城港市| 邓州市| 禹城市| 筠连县| 麻栗坡县| 嘉黎县| 双桥区| 滁州市| 东阿县| 清徐县| 永丰县| 伊金霍洛旗| 郑州市| 吉林省|