Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 一级毛片在线播放,在线欧美成人,国产三级在线观看

          整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          把HTML轉成PDF的4個方案及實現方法

          本文中,我將展示如何使用 Node.js、Puppeteer、headless Chrome 和 Docker 從樣式復雜的 React 頁面生成 PDF 文檔。

          背景:幾個月前,一個客戶要求我們開發一個功能,用戶可以得到 PDF 格式的 React 頁面內容。該頁面基本上是患者病例的報告和數據可視化結果,其中包含許多 SVG。另外還有一些特殊的請求來操縱布局,并對 HTML 元素進行一些重新排列。因此與原始的 React 頁面相比,PDF 中應該有不同的樣式和額外的內容。

          由于這個任務比用簡單的 CSS 規則解決要復雜得多,所以我們先探討了可能的實現方法。我們找到了 3 個主要解決方案。這篇博文將指導你了解它們的可能性并最終實施。

          目錄:

          • 在客戶端還是服務器端生成?
          • 方案1:從 DOM 制作屏幕截圖
          • 方案2:僅使用 PDF 庫
          • 最終方案3:Node.js、Puppeteer 和 Headless Chrome
          • 樣式控制
          • 將文件發送到客戶端并保存
          • 在 Docker 中使用 Puppeteer
          • 方案3 +1:CSS打印規則
          • 總結

          在客戶端還是服務器端生成?

          在客戶端和服務器端都可以生成PDF文件。但是讓后端處理它可能更有意義,因為你并不想耗盡用戶瀏覽器可以提供的所有資源。

          即便如此,我仍然會展示這兩種方法的解決方案。

          方案1:從 DOM 制作屏幕截圖

          乍一看,這個解決方案似乎是最簡單的,事實證明的確是這樣,但它有其自身的局限性。如果你沒有特殊需求,例如在 PDF 中選擇文本或對文本進行搜索,那么這就是一種簡單易用的方法。

          此方法簡單明了:從頁面創建屏幕截圖,并把它放到 PDF 文件中。非常直截了當。我們可以使用兩個包來實現:

          • Html2canvas,根據 DOM 生成截圖
          • jsPdf,一個生成PDF的庫

          開始編碼:

          npm install html2canvas jspdf

          就這樣!

          請注意 html2canvas 的 onclone方法。當你在截圖之前需要操縱 DOM(例如隱藏打印按鈕)時,它是非常方便的。我看到過很多使用這個包的項目。但不幸的是,這不是我們想要的,因為我們需要在后端完成對 PDF 的創建工作。

          方案2:只使用 PDF 庫

          NPM上有幾個庫,如 jsPDF(如上所述)或PDFKit。他們的問題是,如果我想使用這些庫,我將不得不重新調整頁面結構。這肯定會損害可維護性,因為我需要將所有后續更改應用到 PDF 模板和 React 頁面中。

          請看下面的代碼。你需要親自手動創建 PDF 文檔。你需要遍歷 DOM 并找出每個元素并將其轉換為 PDF 格式,這是一項繁瑣的工作。必須找到一個更簡單的方法。

          這段代碼段來自 PDFKit 文檔。但是如果你的目標是直接生成一個 PDF 文件,而不是對一個已經存在的(并且不斷變化的)HTML 頁面進行轉換,它還是很有用的。

          最終方案3:基于 Node.js 的 Puppeteer 和 Headless Chrome

          什么是 Puppeteer?其文檔中寫道:

          Puppeteer 是一個 Node 庫,它提供了一個高級 API 來控制 DevTools 協議上的 Chrome 或 Chromium。 Puppeteer 默認以 headless 模式運行 Chrome 或 Chromium,但其也可以被配置為完整的(non-headless)模式運行。

          它本質上是一個可以從 Node.js 運行的瀏覽器。如果你讀過它的文檔,其中首先提到的就是你可以用 Puppeteer 來生成頁面的截圖和PDF。優秀!這正是我們想要的。

          先用 npmi i puppeteer 安裝 Puppeteer,并實現我們的功能。

          這是一個簡單的功能,可導航到 URL 并生成站點的 PD F文件。

          首先,我們啟動瀏覽器(僅在 headless 模式下支持 PDF 生成),然后打開新頁面,設置視口,并導航到提供的URL。

          設置 waitUntil:'networkidle0' 選項意味著當至少500毫秒沒有網絡連接時,Puppeteer 會認為導航已完成。 (可以從 API docs 獲取更多信息。)

          之后,我們將 PDF 保存為變量,關閉瀏覽器并返回 PDF。

          注意:page.pdf 方法接收 options 對象,你可以使用 'path' 選項將文件保存到磁盤。如果未提供路徑,則 PDF 將不會被保存到磁盤,而是會得到緩沖區。(稍后我將討論如何處理它。)

          如果需要先登錄才能從受保護的頁面生成 PDF,首先你要導航到登錄頁面,檢查表單元素的 ID 或名稱,填寫它們,然后提交表單:

          要始終將登錄憑據保存在環境變量中,不要硬編碼!

          樣式控制

          Puppeteer 也有這種樣式操作的解決方案。你可以在生成 PDF 之前插入樣式標記,Puppeteer 將生成具有已修改樣式的文件。

          await page.addStyleTag({ content: '.nav { display: none} .navbar { border: 0px} #print-button {display: none}' })
          

          將文件發送到客戶端并保存

          好的,現在你已經在后端生成了一個 PDF 文件。接下來做什么?

          如上所述,如果你不把文件保存到磁盤,將會得到一個緩沖區。你只需要把含有適當內容類型的緩沖區發送到前端即可。

          現在,你只需在瀏覽器向服務器發送請求即可得到生成的 PDF。

          一旦發送了請求,緩沖區的內容就應該開始下載了。最后一步是將緩沖區數據轉換為 PDF 文件。

          就這樣!如果單擊“保存”按鈕,那么瀏覽器將會保存 PDF。

          在 Docker 中使用 Puppeteer

          我認為這是實施中最棘手的部分 —— 所以讓我幫你節省幾個小時的百度時間。

          官方文檔指出*“在 Docker 中使用 headless Chrome 并使其運行起來可能會非常棘手”*。官方文檔有疑難解答部分,你可以找到有關用 Docker 安裝 puppeteer 的所有必要信息。

          如果你在 Alpine 鏡像上安裝 Puppeteer,請確保在看到頁面的這一部分時再向下滾動一點。否則你可能會忽略一個事實:你無法運行最新的 Puppeteer 版本,并且你還需要用一個標記禁用 shm :

          const browser = await puppeteer.launch({
           headless: true,
           args: ['--disable-dev-shm-usage']
          });
          

          否則,Puppeteer 子進程可能會在正常啟動之前耗盡內存。

          方案 3 + 1:CSS 打印規則

          可能有人認為從開發人員的角度來看,簡單地使用 CSS 打印規則很容易。沒有 NPM 模塊,只有純 CSS。但是在跨瀏覽器兼容性方面,它的表現如何呢?

          在選擇 CSS 打印規則時,你必須在每個瀏覽器中測試結果,以確保它提供的布局是相同的,并且它不是100%能做到這一點。

          例如,在給定元素后面插入一個 break-after 并不是一個多么高深的技術,但是你可能會驚訝的發現要在 Firefox 中使用它需要使用變通方法。

          除非你是一位經驗豐富的 CSS 大師,在創建可打印頁面方面有很多的經驗,否則這可能會非常耗時。

          如果你可以使打印樣式表保持簡單,打印規則是很好用的。

          讓我們來看一個例子吧。

          @media print {
           .print-button {
           display: none;
           }
           
           .content div {
           break-after: always;
           }
          }
          

          上面的 CSS 隱藏了打印按鈕,并在每個 div 之后插入一個分頁符,其中包含content 類。有一篇很棒的文章總結了你可以用打印規則做什么,以及它們有什么問題,包括瀏覽器兼容性。

          考慮到所有因素,如果你想從不那么復雜的頁面生成 PDF,CSS打印規則非常有效。

          總結

          讓我們快速回顧前面介紹的方案,以便從 HTML 頁面生成 PDF 文件:

          • 從 DOM 產生截圖:當你需要從頁面創建快照時(例如創建縮略圖)可能很有用,但是當你需要處理大量數據時就會有些捉襟見肘。
          • 只用 PDF 庫:如果你打算從頭開始以編程方式創建 PDF 文件,這是一個完美的解決方案。否則,你需要同時維護 HTML 和 PDF 模板,這絕對是一個禁忌。
          • Puppeteer:盡管在 Docker 上工作相對困難,但它為我們的實現提供了最好的結果,而且編寫代碼也是最簡單的。
          • CSS打印規則:如果你的用戶受過足夠的教育,知道如何把頁面內容打印到文件,并且你的頁面相對簡單,那么它可能是最輕松的解決方案。正如你在我們的案例中所看到的,事實并非如此。

          雖然今天是愚人節,但是以上所有內容都是在真的!

          作者:瘋狂的技術宅

          鏈接:https://juejin.im/post/5ca1dc0251882543d569e075

          Java實現根據svg模版動態生成圖片

          使用場景

          需要Java語言動態生成圖片

          用流程圖簡單說明下我這邊工作中使用的場景

          僅供參考

          所以這里就需要生成證書了

          我先給大家看下最終實現的圖片效果

          這里要先說明一下

          • 圖片上的文字都是動態變化的即不同的訂單對應的圖片內容都不一樣
          • 圖片上還可以嵌入圖片哦 比如上圖的logo圖片

          下面說下我是如何解決的

          通過PhantomJS來實現

          這種方式是不能實現這個需求的

          這個的原理就是對網頁截圖 但只能對于靜態頁面截圖 不能根據不同的參數值動態生成圖片

          所以不提倡使用這種方式

          但也介紹下這種使用方式 朋友們根據自己的實際需求情況有選擇的使用

          通過html代碼實現圖片的效果 放入web容器(比如nginx)中部署

          這是h5代碼

          test文件夾下面的內容

          安裝一個docker nginx 將test文件夾加載到nginx容器的/usr/share/nginx/html目錄下面

          docker run --name nginx80  -p 8000:80  -v /tmp/test:/usr/share/nginx/html -d docker.io/nginx
          

          訪問的頁面效果

          訪問該頁面進行截圖

          這張圖片是截圖生成的圖片 但url中的id值并沒有傳給頁面

          在h5代碼中請求后端接口獲取數據動態顯示出來也是不可以的

          所以這種方式使用局限性很窄

          簡單介紹下代碼原理

          大致原理是 通過http請求該url獲取該url的文件流然后解析h5代碼生成圖片

          通過SVG模版動態生成

          先寫svg模版(其實也是h5代碼)

          讀取svg模版 動態傳入參數生成圖片

          其實現原理大致為 讀取svg document h5代碼 將動態參數map解析到h5代碼中 轉換成字節數組 生成圖片格式

          Linux環境圖片中文亂碼

          我本地是mac系統沒有這個問題 在發布到測試環境linux系統出現了這個問題

          先看下問題的現象

          看到了沒 生成的圖片中文全是亂碼

          原因是因為linux系統沒有中文字體

          既然linux系統沒有中文字體 那么就安裝它嘛 let's 盤它!!!

          先看下mac環境的字體情況

          • 安裝字體管理工具
          brew install fontconfig
          
          • 查看支持中文
          fc-list :lang=zh    (注意‘:’前的空格)
          

          mac環境默認會安裝很多中文字體

          再看下linux環境

          • 安裝字體管理工具
          yum -y install fontconfig
          
          • 查看支持中文
          fc-list :lang=zh
          

          果然沒有中文字體

          開始安裝中文字體

          將mac環境的宋體上傳到linux環境

          a 先在mac系統中找到字體安裝目錄

          /System/Library/Fonts
          

          b 找到宋體對應的文件

          c 將該文件上傳到linux指定的目錄下

          /usr/share/fonts/chinese
          

          d 賦予文件夾操作權限

          chmod -R 755 /usr/share/fonts/chinese
          

          e 安裝ttmkfdir來搜索目錄中所有的字體信息,并匯總生成fonts.scale文件

          yum -y install ttmkfdir
          
          ttmkfdir -e /usr/share/X11/fonts/encodings/encodings.dir
          
          

          修改字體配置文件

          vi /etc/fonts/fonts.conf
          添加
          <dir>/usr/share/fonts/chinese</dir>
          

          刷新內存中的字體緩存

          fc-cache
          

          確認是否安裝成功

          在jdk中安裝該宋體

          a 找到jdk所在的安裝目錄

          echo $JAVA_HOME 
          

          b 將宋體文件復制過來

          cp /usr/share/fonts/chinese/STHeiti\ Light.ttc /usr/local/software/jdk1.8.0_141/jre/lib/fonts/fallback
          
          fallback代表存放后備語言的文件夾
          

          重啟java服務即可

          DEMO代碼

          https://gitee.com/pingfanrenbiji/resource/tree/master/image
          

          注意: 引入的依賴問題

            <!--phantomjs -->
            <dependency>
             <groupId>org.seleniumhq.selenium</groupId>
             <artifactId>selenium-java</artifactId>
             <version>2.53.1</version>
            </dependency>
            <dependency>
             <groupId>com.github.detro</groupId>
             <artifactId>ghostdriver</artifactId>
             <version>2.1.0</version>
            </dependency>
          
            <!--svg-->
            <dependency>
             <groupId>com.github.hui.media</groupId>
             <artifactId>svg-core</artifactId>
             <version>2.5</version>
            </dependency>
          
          

          這些依賴jar包我是上傳到了公司的私服上了

          若是朋友們下拉不下來

          我提供給大家這些底層jar包的實現源碼

          https://gitee.com/pingfanrenbiji/quick-media
          

          自行上傳到自己的私服即可

          天給大家分享一款超全功能的跨瀏覽器平臺甘特圖表庫DHTMLXGantt

          dhtmlx-gantt DHTMLX公司開源的 JavaScript 甘特圖/橫道圖/條狀圖類庫。用來快速構建顯示項目、進度,和隨著時間關聯的相關進展情況。

          說明

          dhtmlx-Gantt 由位于俄羅斯圣彼得堡DHTMLX公司開發的甘特圖組件,適用于B/S模式的Web應用開發。被廣泛應用于項目管理、建筑、IT軟件、汽車等領域。

          快速創建

          <!DOCTYPE html>
          <html>
          <head>
          	<meta http-equiv="Content-type" content="text/html; charset=utf-8">
          	<title>gantt demo</title>
          	<script src="dhtmlxgantt.js?v=6.0.0"></script>
          	<link rel="stylesheet" href="dhtmlxgantt.css?v=6.0.0">
          	<style>
          		html, body {
          			height: 100%;
          			padding: 0px;
          			margin: 0px;
          			overflow: hidden;
          		}
          	</style>
          </head>
          <body>
          <div id="gantt_here" style='width:100%; height:100%;'></div>
          <script>
          	var taskList = {
          		data: [
          			{
          				id: 1, text: "Project #2", start_date: "01-04-2018", duration: 18, order: 10,
          				progress: 0.4, open: true
          			},
          			{
          				id: 2, text: "Task #1", start_date: "02-04-2018", duration: 8, order: 10,
          				progress: 0.6, parent: 1
          			},
          			{
          				id: 3, text: "Task #2", start_date: "11-04-2018", duration: 8, order: 20,
          				progress: 0.6, parent: 1
          			}
          		],
          		links: [
          			{id: 1, source: 1, target: 2, type: "1"},
          			{id: 2, source: 2, target: 3, type: "0"}
          		]
          	};
          	
          	gantt.config.date_format = "%Y-%m-%d %H:%i";
          	gantt.init("gantt_here");
          	gantt.parse(taskList);
          </script>
          </body>
          </html>

          為了配置甘特圖所需外觀,dhtmlxGantt提供了2個對象 configtemplates

          gantt.config //日期,比例,控件等的配置選項。
          gantt.templates //格式化甘特圖中使用的日期和標簽的模板。
          • gantt.config 年示圖
          gantt.config.scale_unit = "year"; //按年顯示
          gantt.config.step = 1.5;	//設置時間刻度的步長(X軸)
          gantt.config.date_scale = "%Y";	//日期尺度按年
          
          gantt.init("gantt_here");

          • gantt.config 月示圖
          gantt.config.scale_unit = "month"; //按月顯示
          gantt.config.date_scale = "%F, %Y"; //設置時間刻度的格式(X軸) 多個尺度
          
          gantt.config.scale_height = 50; //設置時間刻度的高度和網格的標題
          
          gantt.config.subscales = [
          	{unit: "day", step: 1, date: "%j, %D"}
          ]; //指定第二個時間刻度
          
          gantt.init("gantt_here");

          • gantt.templates 可用于更改日期和標簽的顯示。
          gantt.templates.task_text=function(start,end,task){
          	return "<b>Text:</b> "+task.text+",<b> Holders:</b> "+task.username;
          };
          gantt.init("gantt_here");

          官網提供了豐富的文檔示例。

          非常棒的一款開源甘特圖庫,可以讓你預測時間、成本、數量及質量上的關聯并回溯結果。也能幫助你考慮人力、資源、日期、項目中重復的要素和關鍵部分,讓你更加直觀的看到任務進展及資源的利用率等。

          # 官網地址
          https://dhtmlx.com/docs/products/dhtmlxGantt/
          
          # 倉庫地址
          https://github.com/DHTMLX/gantt

          好了,今天就介紹到這里。大家如果有其它不錯的甘特圖庫,歡迎一起交流討論!


          主站蜘蛛池模板: 国产精品香蕉一区二区三区| 中文字幕精品无码一区二区| 日韩美女在线观看一区| 国产成人一区二区三区免费视频 | 国产成人精品一区二区秒拍| 中文字幕精品一区影音先锋| 极品人妻少妇一区二区三区| 久久中文字幕无码一区二区| 丰满爆乳无码一区二区三区| 国内精品视频一区二区三区八戒| 日韩精品乱码AV一区二区| 三上悠亚一区二区观看| 国产av天堂一区二区三区| 人妻激情偷乱视频一区二区三区| 好爽毛片一区二区三区四| 国产成人一区二区精品非洲 | 日韩精品国产一区| 精品一区二区三区在线视频观看| 一区二区三区影院| 日本无卡码免费一区二区三区| 中文字幕无码免费久久9一区9| 国产亚洲3p无码一区二区| 中文字幕精品一区二区2021年| 精品人妻少妇一区二区三区| 少妇一夜三次一区二区| 人妻体内射精一区二区三区| 亚洲AV本道一区二区三区四区| 国产日韩精品一区二区在线观看| 亚洲综合色一区二区三区| 国产精品视频一区二区三区经| 精品不卡一区二区| 国产成人免费一区二区三区| 精品久久一区二区三区| 人妻少妇精品一区二区三区| 中文字幕无码一区二区免费| 亚欧色一区W666天堂| 夜夜高潮夜夜爽夜夜爱爱一区| 精品成人av一区二区三区| 日韩AV无码一区二区三区不卡毛片| 国产无套精品一区二区| 无码视频一区二区三区|