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

Java調(diào)用Vue前端頁面生成PDF文件的完整代碼

 更新時間:2025年10月21日 08:26:55   作者:Aikes902  
在Vue應(yīng)用中,將頁面導(dǎo)出為PDF文件通常涉及到前端技術(shù)的組合,這篇文章主要介紹了Java調(diào)用Vue前端頁面生成PDF文件的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下

一、業(yè)務(wù)背景

在實(shí)際業(yè)務(wù)使用中,有些情況下打印功能是由后端組裝數(shù)據(jù),前端整理數(shù)據(jù)生成pdf文件。此時如果某個功能需要后端再拿到生成的pdf進(jìn)行下一步處理就不好實(shí)現(xiàn)。

比如后端需要拿到pdf文件發(fā)給CA廠商進(jìn)行鑒權(quán),如果在之前基礎(chǔ)上增加新的交互邏輯整個流程就變得復(fù)雜冗余,于是我們考慮后端直接調(diào)用前端獲取pdf文件。

二、流程概覽

頁面點(diǎn)擊觸發(fā)——>后端組裝參數(shù)調(diào)用Vue生成PDF——>前端收到請求解析參數(shù)繪制PDF——>后端拿到PDF文件進(jìn)行后續(xù)業(yè)務(wù)處理(CA鑒權(quán)等)

其中關(guān)鍵的一點(diǎn)在于后端訪問后需要等待多久再生成PDF,如果固定某個時間間隔可能會出現(xiàn)PDF沒生成全或者已經(jīng)生成完成但是還在等待浪費(fèi)時間。

所以約定了一個屬性,當(dāng)前端頁面渲染完成給這個屬性打標(biāo)記,后端讀取標(biāo)記成功后生成PDF。

三、環(huán)境準(zhǔn)備

該功能需要依賴瀏覽器,我們以谷歌為例,確認(rèn)好本地谷歌瀏覽器版本,下載對應(yīng)的瀏覽器驅(qū)動。(驅(qū)動下載地址:Chrome for Testing availability

大版本必須一致(139),然后將下載好的驅(qū)動放到固定位置,谷歌瀏覽器exe位置也需要摘出來,稍后需要在Java代碼中配置。

四、后端代碼

需要將驅(qū)動路徑、瀏覽器路徑,前端訪問路徑進(jìn)行配置,前端訪問路由可自行調(diào)整。以下是具體代碼,整體流程簡單需要調(diào)試的配置較多。

private String dllUrl;//存儲驅(qū)動的根目錄,完整路徑代碼拼接,可自行調(diào)整

private String mWebAddress;//存儲前端訪問頁面,后續(xù)訪問路由代碼拼接,可自行調(diào)整

private String chromePath;//瀏覽器啟動程序完整路徑,可自行調(diào)整

package com.aikes.util;

import lombok.extern.slf4j.Slf4j;
import org.openqa.selenium.By;
import org.openqa.selenium.Pdf;
import org.openqa.selenium.PrintsPage;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.print.PrintOptions;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.time.Duration;
import java.util.Base64;
import java.util.Collections;

/**
 * 調(diào)用vue頁面獲取PDF文件
 */
@Slf4j
@Service
public class WebAccessServerUtil {

    @Value("${dllUrl:D:/DLL}")
    private String dllUrl;

    @Value("${webAddress:http://127.0.0.1:8080/mcpc/ui/dist/index.html}")
    private String mWebAddress;

    @Value("${chromePath:C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe}")
    private String chromePath;

    public boolean getPdfFromWeb(String cPath,String cpk_notification,String cpk_emgency){

        log.info("根目錄:" + dllUrl);
        log.info("Web端訪問地址:" + mWebAddress);
        log.info("谷歌瀏覽器路徑:" + chromePath);

        // 完全禁用WebDriverManager自動下載,手動指定驅(qū)動路徑(避免版本沖突)
        System.setProperty("wdm.enabled", "false");
        // 手動指定本地ChromeDriver路徑(替換為你的實(shí)際路徑)
        //驅(qū)動版本需要和服務(wù)器瀏覽器版本對應(yīng)   138.0.7204.158
        System.setProperty("webdriver.chrome.driver", dllUrl + File.separator + "chromedriver" + File.separator + "chromedriver.exe");
        System.setProperty("webdriver.chrome.bin", chromePath);

        // 配置瀏覽器選項(xiàng)(重點(diǎn)修復(fù))
        ChromeOptions options = new ChromeOptions();
        options.addArguments("--headless=new"); // 新版headless模式
        options.addArguments("--disable-gpu");
        options.addArguments("--no-sandbox");
        options.addArguments("--disable-dev-shm-usage");
        options.addArguments("--remote-allow-origins=*"); // 允許跨域WebSocket
        options.setExperimentalOption("excludeSwitches", Collections.singletonList("enable-automation"));

        WebDriver driver = new ChromeDriver(options);
        WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(15)); // 最大等待10秒

        try {

            String vuePageUrl = mWebAddress + "#/generatePdfTest?pk_notification=" + cpk_notification + "&pk_emgency=" + cpk_emgency;
            driver.get(vuePageUrl);

            // 智能等待:直到頁面設(shè)置true
            wait.until(ExpectedConditions.attributeToBe(
                    By.tagName("body"), "data-pdf-ready", "true"
            ));

            PrintOptions printOptions = new PrintOptions();
            printOptions.setBackground(true);
            printOptions.setPageRanges("1-5");

            // 替換原PDF字節(jié)處理代碼
            Pdf pdf = ((PrintsPage) driver).print(printOptions);
            String base64Pdf = pdf.getContent(); // 獲取Base64編碼的PDF內(nèi)容
            byte[] pdfBytes = Base64.getDecoder().decode(base64Pdf); // 解碼為原始二進(jìn)制

            Files.write(Paths.get(cPath), pdfBytes);
            log.info("調(diào)用Web端生成PDF文件成功: " + cPath);
            return true;
        } catch (Exception e) {
            log.error("獲取Web端PDF文件失敗:{}", e.getMessage(), e);
            return false;
        } finally {
            try {
                driver.quit();
            } catch (Exception ignore) {
            }
        }
    }
}

五、前端代碼

前端vue僅供測試使用頁面,具體業(yè)務(wù)使用需要進(jìn)行美化和數(shù)據(jù)填充

在路由配置文件增加如下配置,實(shí)現(xiàn)路由和文件的綁定

    {
      path: '/generatePdfTest',
      name: 'GeneratePDFTest',
      component: (resolve) =>
        require(['@/components/notificationRecord/MedicalNotificationPdf'], resolve),
    }

具體pdf生成頁面代碼如下

<template>
  <div class="pdf-container">
    <h1>{{ title }}</h1>
    <div v-for="item in items" :key="item.id" class="item">
      <p><strong>{{ item.label }}:</strong> {{ item.value }}</p>
    </div>
  </div>
</template>

<script>
  export default {
    data() {
      return {
        title: '測試通知記錄書',
        items: []
      }
    },
    mounted() {
      try {
        // 檢查路由是否可用(避免this.$route未定義的錯誤)
        if (!this.$route) {
          throw new Error("Vue Router未正確配置");
        }
        const recordId = this.$route.query.id || 'default';

        // 模擬數(shù)據(jù)加載
        setTimeout(() => {
          this.items = [
            { id: 1, label: '患者姓名', value: '張三' },
            { id: 2, label: '病歷號', value: recordId },
            { id: 3, label: '診斷結(jié)果', value: 'stemi' },
            { id: 4, label: '診斷日期', value: '2025-08-12' },
            { id: 5, label: '診斷醫(yī)生', value: '李四' }
          ];

          // 確認(rèn)body元素存在后再設(shè)置屬性
          if (document.body) {
            document.body.setAttribute('data-pdf-ready', 'true');
            console.log("PDF渲染標(biāo)記已設(shè)置"); // 用于瀏覽器控制臺調(diào)試
          } else {
            console.error("body元素不存在,無法設(shè)置標(biāo)記");
          }
        }, 500);
      } catch (error) {
        console.error("組件加載錯誤:", error);
      }
    }
  }
</script>

<style scoped>
  /* 樣式保持不變 */
  .pdf-container {
    width: 210mm;
    margin: 0 auto;
    padding: 20px;
    font-family: "SimSun";
  }
  .item {
    margin: 10px 0;
  }
</style>

六、最終效果

頁面查看網(wǎng)頁P(yáng)DF

后端調(diào)用生成的PDF      

七、總結(jié)

該功能僅作為“曲線救國”方案,實(shí)際業(yè)務(wù)場景需要盡可能預(yù)想到該流程提前設(shè)計(jì)交互思路,供大家參考學(xué)習(xí)哈。

到此這篇關(guān)于Java調(diào)用Vue前端頁面生成PDF文件的文章就介紹到這了,更多相關(guān)Java調(diào)用Vue前端生成PDF文件內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 淺析java中asList的使用詳解

    淺析java中asList的使用詳解

    Java中的asList方法是數(shù)組工具類 Arrays中的一個靜態(tài)方法,asList()方法把數(shù)組轉(zhuǎn)換成集合時,不能使用其修改集合相關(guān)的方法,本文通過示例代碼給大家介紹java asList使用,感興趣的朋友一起看看吧
    2021-10-10
  • Java foreach相關(guān)原理及用法解析

    Java foreach相關(guān)原理及用法解析

    這篇文章主要介紹了Java foreach相關(guān)原理及用法解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-07-07
  • 通過System.getProperty配置JVM系統(tǒng)屬性

    通過System.getProperty配置JVM系統(tǒng)屬性

    這篇文章主要介紹了通過System.getProperty配置JVM系統(tǒng)屬性,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-10-10
  • GateWay路由規(guī)則與動態(tài)路由詳細(xì)介紹

    GateWay路由規(guī)則與動態(tài)路由詳細(xì)介紹

    這篇文章主要介紹了GateWay路由規(guī)則與GateWay動態(tài)路由,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-09-09
  • Java并發(fā)中線程封閉知識點(diǎn)詳解

    Java并發(fā)中線程封閉知識點(diǎn)詳解

    在本篇文章里我們給大家整理了關(guān)于Java并發(fā)中線程封閉的知識點(diǎn)總結(jié)內(nèi)容,需要的朋友們學(xué)習(xí)參考下。
    2019-07-07
  • Spring bean為什么需要依賴注入

    Spring bean為什么需要依賴注入

    本篇文章主要介紹了Spring依賴注入的三種方式小結(jié),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2021-07-07
  • java實(shí)現(xiàn)利用String類的簡單方法讀取xml文件中某個標(biāo)簽中的內(nèi)容

    java實(shí)現(xiàn)利用String類的簡單方法讀取xml文件中某個標(biāo)簽中的內(nèi)容

    下面小編就為大家?guī)硪黄猨ava實(shí)現(xiàn)利用String類的簡單方法讀取xml文件中某個標(biāo)簽中的內(nèi)容。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-12-12
  • SpringBoot中MybatisX插件的簡單使用教程(圖文)

    SpringBoot中MybatisX插件的簡單使用教程(圖文)

    MybatisX 是一款基于 IDEA 的快速開發(fā)插件,方便在使用mybatis以及mybatis-plus開始時簡化繁瑣的重復(fù)操作,本文主要介紹了SpringBoot中MybatisX插件的簡單使用教程,感興趣的可以了解一下
    2023-06-06
  • 詳解Java 包掃描實(shí)現(xiàn)和應(yīng)用(Jar篇)

    詳解Java 包掃描實(shí)現(xiàn)和應(yīng)用(Jar篇)

    這篇文章主要介紹了詳解Java 包掃描實(shí)現(xiàn)和應(yīng)用(Jar篇),本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-07-07
  • FreeMarker如何調(diào)用Java靜態(tài)方法及靜態(tài)變量方法

    FreeMarker如何調(diào)用Java靜態(tài)方法及靜態(tài)變量方法

    這篇文章主要介紹了FreeMarker如何調(diào)用Java靜態(tài)方法及靜態(tài)變量方法,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-12-12

最新評論

双鸭山市| 柘荣县| 浦城县| 延庆县| 奉贤区| 连州市| 株洲市| 潍坊市| 逊克县| 苍溪县| 白水县| 喀什市| 安丘市| SHOW| 湾仔区| 武强县| 固阳县| 五常市| 麻栗坡县| 肃南| 柳林县| 旬阳县| 盈江县| 雷波县| 合水县| 屯门区| 南汇区| 隆安县| 万年县| 大庆市| 韶山市| 广南县| 恩施市| 克拉玛依市| 临海市| 湖北省| 红安县| 临西县| 临城县| 昆明市| 拜泉县|