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

基于SpringBoot實現(xiàn)HTML轉PDF功能的常用方式

 更新時間:2025年10月12日 11:38:13   作者:智_永無止境  
你是否因為Html轉PDF發(fā)愁?又是否因為中文亂碼而心煩意亂?又是否因為格式導致PDF排版錯亂而苦惱?所以本文小編給大家介紹了基于SpringBoot實現(xiàn)HTML轉PDF功能的常用方式,需要的朋友可以參考下

01 引言

你是否因為HtmlPDF發(fā)愁?又是否因為中文亂碼而心煩意亂?又是否因為格式導致PDF排版錯亂而苦惱?…

在企業(yè)里,我們經(jīng)常會遇到下載PDF報告的場景,前端展示還好,可以使用pdf.js類似的框架處理,但是很多時候,需要服務端自己渲染數(shù)據(jù)然后,上傳或者郵件發(fā)送。好好的頁面,轉成PDF直接錯亂了,只能一點點的調(diào)試,才能完成。過程費時費力。

這不,前兩天正好遇到HtmlPDF的需求,調(diào)整了許久的樣式才完成PDF的完美轉化。

02 框架選型

Html轉化成PDF的框架有很多,小編也試了好幾種,將覺得好用的分享給大家。

2.1 io.woo.htmltopdf

Maven

<dependency>
	<groupId>io.woo</groupId>
	<artifactId>htmltopdf</artifactId>
	<version>1.0.4</version>
</dependency>
<!-- Thanks for using https://jar-download.com -->

官網(wǎng)地址:https://jar-download.com

GitHub地址:https://github.com/wooio/htmltopdf-java

2.2 openhtmltopdf

Maven

<dependency>
    <groupId>com.openhtmltopdf</groupId>
    <artifactId>openhtmltopdf-core</artifactId>
    <version>1.0.10</version>
</dependency>
<dependency>
    <groupId>com.openhtmltopdf</groupId>
    <artifactId>openhtmltopdf-pdfbox</artifactId>
    <version>1.0.10</version>
</dependency>

GitHub地址:https://github.com/danfickle/openhtmltopdf

2.3 Flying Saucer

Maven

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

GitHub地址:https://github.com/flyingsaucerproject/flyingsaucer

03 Springboot集成thymeleaf

3.1 Maven依賴

這里暫時忽略HtmlPDF的依賴,后面按需引入。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 模板引擎 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

<!-- html 2 pdf 工具 -->

3.2 頁面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <title>評估報告</title>
</head>
<body>
<div class="total-container">
    <div class="container" th:each="item:${list}">
        <input type="hidden" th:value="${item.licenseCode}" name="licenseCode" />
        <div class="img-container">
            <img th:src="${item.image1}" />
            <img th:src="${item.image2}" />
        </div>
        <div class="title" th:text="${item.vehicleName}"></div>
        <div>
            <ul>
                <li>
                    <label>品牌:</label>
                    <span th:text="${item.brandName}"></span>
                </li>
                <li>
                    <label>車系:</label>
                    <span th:text="${item.seriesName}"></span>
                </li>
                <li>
                    <label>年款:</label>
                    <span th:text="${item.modelYear}"></span>
                </li>
                <li>
                    <label>上牌年月:</label>
                    <span th:text="${item.licenseYear}"></span>
                </li>
                <li>
                    <label>里程(公里):</label>
                    <span th:text="${item.displayMileage}"></span>
                </li>
                <li>
                    <label>成交日期:</label>
                    <span th:text="${item.dealDate}"></span>
                </li>
                <li style="border-bottom: none;">
                    <label>成交價(元):</label>
                    <span th:text="${item.dealPrice}"></span>
                </li>
            </ul>
        </div>
    </div>
</div>
</body>
</html>

這里描述了車輛的信息

3.3 數(shù)據(jù)渲染

@RequestMapping("index")
public String index(Model model) {
    List<Map<String, Object>> list = new ArrayList<>();
    for (int i = 0; i < 3; i++) {
        Map<String, Object> item = new HashMap<>();
        item.put("image1", "http://img.example.com/a.jpg");
        item.put("image2", "http://img.example.com/b.jp");
        item.put("vehicleName", "路虎Defender[衛(wèi)士](進口)2023款Defender130 48V[衛(wèi)士 130 48V] 3.0T手自-體P400 HSE");
        item.put("brandName", "路虎");
        item.put("seriesName", "Defender[衛(wèi)士]");
        item.put("modelYear", "2023款");
        item.put("licenseYear", SDF.format(new Date()));
        item.put("displayMileage", DF.format(new BigDecimal("9657")));
        item.put("dealDate", SDF.format(new Date()));
        item.put("dealPrice", DF.format(new BigDecimal("1000000")));

        list.add(item);
    }
    model.addAttribute("list", list);
    return "index";
}

3.4 渲染效果

左右沒有留白。

04 Html轉PDF

上面已經(jīng)完成Html的渲染和展示。我們只需要拿到Html并通過工具,轉化成PDF即可。

HtmlPDF不需要通過瀏覽器渲染,需要服務端直接渲染并拿到渲染之后的Html。渲染的代碼塊:

Map<String, Object> map = new HashMap<>();
map.put("list", list);

Context context = new Context(Locale.getDefault(), map);
String html = templateEngine.process("index", context);
System.out.println(html);

4.1 io.woo.htmltopdf

核心方法:

InputStream convert = HtmlToPdf.create()
                .object(HtmlToPdfObject.
                        forHtml(htmlContent)
                        .defaultEncoding("utf-8"))
                .convert();

IOUtils.copyLarge(convert, response.getOutputStream());

效果

我們會發(fā)現(xiàn)轉成PDF之后,左右會自動留白?,F(xiàn)在的問題是,圖片需要調(diào)整一下,調(diào)整到左右留白差不多,這個是難點。

應該怎么去調(diào)整呢?

因為生成的PDF默認都是基于A4的尺寸:21cm*29.7cm。所以我們直接將寬度設置為21cm。

.container{
    width: 21cm;
    /*設置邊框方便查看*/
    box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
}

轉成PDF之后右邊距還是有較大的空隙的:

我們繼續(xù)加大寬度,最終結果:寬度設置23cm比較合適。此時,就可在頁面上愉快的調(diào)整圖片或者其他與元素了。

4.2 openhtmltopdf

核心方法

PdfRendererBuilder builder = new PdfRendererBuilder();
builder.withHtmlContent(htmlContent, null);
builder.toStream(response.getOutputStream());

// 配置字體支持中文
builder.useFont(new File("C:\\Windows\\Fonts\\simhei.ttf"), "SimHei");

builder.run();

注意事項

需要設置支持中的字體,且頁面的font-family需要明確指出

font-family: "SimHei";

頁面元素必須要有閉合標簽,否則報錯

調(diào)整

調(diào)整依然是難點。經(jīng)過測試,該框架的的PDFA4紙的大小基本一致。而內(nèi)容則是去除留白的長度。

經(jīng)過測量:PDF長度794px,兩邊留白56px,所以頁面長度:794-56-56 = 682px

調(diào)正頁面長度:

.container{
    font-family: "SimHei";
    width: 682px;
    box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
}

效果非常完美:

4.3 Flying Saucer

核心方法

ITextRenderer renderer = new ITextRenderer();
renderer.getFontResolver().addFont("C:\\Windows\\Fonts\\simh	ei.ttf", BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED);
renderer.setDocumentFromString(htmlContent);
renderer.layout();
renderer.createPDF(response.getOutputStream());

這里同樣要設置支持中文,和openhtmltopdf配置類似。

調(diào)整方式同4.2openhtmltopdf本身就是基于Flying Saucer,所以這里就不在演示,兩個同宗同源。

05 小結

每一款軟件都是其特定標準,調(diào)整的順序也不一樣。無論如何,解決問題的思路是一致的。相比較io.woo.htmltopdf可能更加方便,本身就支持中文,而其他兩個則需要單獨配置才能支持中文。你們更喜歡哪一種呢?

以上就是基于SpringBoot實現(xiàn)HTML轉PDF功能的常用方式的詳細內(nèi)容,更多關于SpringBoot實現(xiàn)HTML轉PDF的資料請關注腳本之家其它相關文章!

相關文章

  • 詳解如何在SpringBoot中使用WebMvc

    詳解如何在SpringBoot中使用WebMvc

    Spring?Boot?是一個快速、簡單的開發(fā)框架,在?Spring?Boot?中,我們可以使用?WebMvc?來構建?Web?應用程序,所以本文就來講講如何在SpringBoot中使用WebMvc吧
    2023-06-06
  • Java布爾值Boolean和boolean之間轉換實例用法

    Java布爾值Boolean和boolean之間轉換實例用法

    在本篇文章里小編給大家整理的是一篇關于Java布爾值Boolean和boolean之間轉換實例用法內(nèi)容,有需要的朋友們跟著學習參考下。
    2021-06-06
  • Java打亂ArrayList生成一個隨機序列列表

    Java打亂ArrayList生成一個隨機序列列表

    有時候會需要將一個ArrayList或者數(shù)組中的數(shù)字打亂,方便后續(xù)使用,比如隨機出題、答案選項打亂、連線題打亂、抽獎號碼打亂等等,把我自己寫的一段代碼貼出來分享給大家。
    2016-08-08
  • Java中日期格式化YYYY-DD的操作bug

    Java中日期格式化YYYY-DD的操作bug

    這篇文章主要介紹了Java中日期格式化YYYY-DD中遇到的坑,本文給大家分享到腳本之家平臺,需要的朋友可以參考下
    2020-01-01
  • SpringBoot之瘦身部署問題

    SpringBoot之瘦身部署問題

    這篇文章主要介紹了SpringBoot之瘦身部署問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • 解決java idea新建子目錄時命名不是樹形結構的問題

    解決java idea新建子目錄時命名不是樹形結構的問題

    這篇文章主要介紹了解決java idea新建子目錄時命名不是樹形結構的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-08-08
  • Java如何提高大量數(shù)據(jù)的處理性能

    Java如何提高大量數(shù)據(jù)的處理性能

    在Java中提高大量數(shù)據(jù)的處理性能,可以從多個角度進行優(yōu)化,包括選擇合適的數(shù)據(jù)結構,使用多線程和并發(fā)處理等,下面我們來看看Java提高大量數(shù)據(jù)的處理性能的實用技巧吧
    2025-01-01
  • Java線程安全解決方案(synchronized,ReentrantLock,Atomic)

    Java線程安全解決方案(synchronized,ReentrantLock,Atomic)

    這篇文章主要介紹了Java線程安全解決方案(synchronized,ReentrantLock,Atomic),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-09-09
  • 淺談java二進制、十進制、十六進制、字符串之間的相互轉換

    淺談java二進制、十進制、十六進制、字符串之間的相互轉換

    下面小編就為大家?guī)硪黄獪\談二進制、十進制、十六進制、字符串之間的相互轉換。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考,一起跟隨小編過來看看吧
    2016-06-06
  • 深入理解Mybatis二級緩存

    深入理解Mybatis二級緩存

    與一級緩存相比,二級緩存范圍更大了一些,可以被多個SqlSession所共用。下面通過本文帶領大家一起學習mybatis二級緩存知識,一起看看吧
    2016-12-12

最新評論

广元市| 汉川市| 抚远县| 韶关市| 胶南市| 铜山县| 六盘水市| 五台县| 梓潼县| 诸暨市| 西林县| 伊金霍洛旗| 海口市| 芜湖县| 木里| 五常市| 菏泽市| 遂宁市| 迭部县| 勃利县| 休宁县| 胶州市| 萍乡市| 当涂县| 佛学| 福清市| 乐陵市| 芮城县| 大连市| 盈江县| 远安县| 彭山县| 武冈市| 松原市| 庄河市| 门源| 广安市| 庆安县| 西青区| 龙州县| 锡林浩特市|