TechMoon 科技月球
WordPress、SEO 與 AI 工具實測指南
TechMoon 科技月球
WordPress、SEO 與 AI 工具實測指南

BKHTMLTOPDF 把 Chromium 嵌進 Java 服務,用 HTTP API 就能把 HTML 排成 PDF。本篇實測社群版:兩頁中文文件約 0.18 秒、字型直接內嵌,並拆解免費版必須有顯示伺服器、無頭與雲端屬付費範圍的真實邊界。
用 AI 摘要這篇文章:
開發者要找 HTML 轉 PDF 方案時,通常會先撞到兩堵牆:純後端函式庫排不出複雜版面,瀏覽器自動化又要另外養一套 Node 環境。BKHTMLTOPDF 走第三條路:把整個 Chromium 嵌進 Java 服務裡,丟一段 HTML 給 HTTP API,它回傳一份排好的 PDF。我在 macOS 上實際把社群版 0.0.6 跑起來測過:一份兩頁的中文請款單(含 flex 卡片、表格、強制換頁)轉換來回約 0.18 秒,十頁文件約 0.2 秒,中文字型會直接嵌進 PDF 檔裡。
不過最該先講的判斷是:它的免費與付費邊界畫在「部署環境」上,不是功能多寡。免費的社群版必須跑在有螢幕(顯示伺服器)的機器上,一般雲端那種無頭 Linux 伺服器屬於付費企業版的範圍。先搞清楚這條線,再談它值不值得用。
BKHTMLTOPDF 是 2025 年 10 月出現的開源專案,用 Java 21 加 Spring Boot 寫成,核心是把 Chromium 的 Blink 排版引擎透過 JCEF(Java Chromium Embedded Framework)嵌進同一個 Java 服務。實際打開它的 pom.xml 看,渲染相依是 jcefmaven 141.0.10(版號跟著 Chromium 走),PDF 處理用 Apache PDFBox,Markdown 轉換用 JetBrains 的 markdown-jvm。

它對外就是四個 HTTP 端點:
POST /html-to-pdf:吃 JSON 格式的 HTML 字串,回傳 PDF 串流POST /md-to-pdf:輸入 Markdown,內部先轉 HTML 再排 PDFPOST /pdf-to-jpg:上傳 PDF,回傳打包每頁 JPG 的 ZIPGET /fonts:字型相關資訊PDF 參數支援頁首頁尾模板(headerTemplate 與 footerTemplate)、可選擇產生標籤式 PDF 與文件大綱,標籤式 PDF 對螢幕閱讀器與無障礙場景有實際意義;列印等待條件可以選 load、domcontentloaded 或手動訊號,預設 15 秒逾時,檔案上傳(例如 PDF 轉 JPG)的單次請求上限 32MB。整包服務就是一個 JAR 檔,從 GitHub Release 下載後用 JDK 21 直接 java -jar 就能起來,不需要另外裝 Node 或下載瀏覽器。
架構上有一個值得展開的細節:Chromium 引擎在服務裡是常駐的(底層是 CEF 原生程序組),每筆轉換建立一個獨立的 client 與頁面,轉完就釋放。這跟「每次轉換都冷啟動一個瀏覽器程序」的做法相比,省掉了反覆初始化的成本,這也是它熱啟動能壓在零點幾秒的結構性原因。對應的取捨是整個服務共用一個引擎實例,官方企業版文件才會強調程序隔離與長時間運行的記憶體管理是付費版的優化重點。
我把社群版 0.0.6 的 JAR 抓下來,在本機用 OpenJDK 21 跑。第一次啟動花了 18.5 秒,其中大半是 JCEF 自動下載並安裝 Chromium 二進位檔的時間,之後啟動就不再重複這段。之後的轉換量測都是熱啟動狀態:
| 測試項目 | 來回時間 | 輸出 |
|---|---|---|
| 兩頁中文請款單(flex、表格、換頁) | 0.175 至 0.199 秒 | 87KB PDF |
| 含中文字型內嵌的完整版面 | 約 0.24 秒 | 222KB PDF |
| 十頁文件 | 0.198 至 0.215 秒 | 78KB PDF |
| Markdown(標題、表格、程式碼區塊) | 0.24 至 0.34 秒 | 40KB PDF |
| 兩頁 PDF 轉 JPG | 約 0.21 秒 | ZIP 內含每頁 JPG |
幾個實際觀察:中文、粗體、清單、表格在 Markdown 轉出來的 PDF 裡都正常;強制換頁(page-break-after)照著 CSS 生效,十頁就是十頁;PDF 轉 JPG 回的是 ZIP,裡面每頁一張 612 乘 792 的 Letter 尺寸圖檔,解析度有 0.1 到 5 倍的縮放參數可調。字型內嵌這點對中文場景特別實用,收件的人不需要剛好裝了同樣的字型。要留意的是社群版的字型來自主機環境:我本機測中文,Chromium 抓的是系統的字型再嵌進 PDF;換到一台沒裝中文字型的精簡版 Linux,同一段 HTML 預期會遇到字型缺字問題。企業版文件則寫明預設內建一批 Google Fonts 並標註免費商用授權,這也是兩個版本在文件分類上實際差異化的一環。平台支援方面,官方系統需求列了 Windows 10 以上、macOS 與 Linux,外加 Chromium 135 以上。

實際呼叫長這樣,文件端點收 JSON、回 PDF 串流:
curl -X POST http://127.0.0.1:8080/html-to-pdf \
-H 'Content-Type: application/json' \
-d '{"text": "<html><body>Hi, bkhtmltopdf.</body></html>"}' \
--output out.pdf
請求裡的 text 放完整 HTML,複雜版面建議把 CSS 與 JavaScript 直接內嵌在文件裡,減少外部載入的等待與不確定性。頁首頁尾、標籤式 PDF、大綱這些 PDF 參數放在 pdf 物件,等待條件放在 options 物件,形狀與瀏覽器列印參數是同一套概念,寫過 Puppeteer 頁面列印的人會直接看懂。
官方效能頁另有自己的數字:宣稱 10 頁 HTML 轉 PDF 平均約 60 毫秒。這是站方在 8 核心、8GB 記憶體的 Docker 環境下,取三次熱啟動平均的自報數字,量測邊界官方沒有載明,從數字看應不含 HTTP 來回;我自己量的是包含 HTTP 來回的本機時間,兩種口徑不能直接互換,但至少在本機開發場景,它的速度不是瓶頸。
這是整個專案最關鍵、也最容易被行銷頁蓋過去的事實。官方系統需求頁寫得很明白:社群版不支援無頭模式,機器必須有顯示伺服器,Linux 要有 X11,macOS 用 Aqua,Windows 要有桌面。文件裡的比喻是「把它想成一台螢幕」,Chromium 需要一個虛擬桌面環境來排版。README 也重複了同樣的話:需要無頭運行請購買企業版。
這不是理論限制。GitHub issue #7 有人把服務部署到 Red Hat 8.8 伺服器,服務本身起來了,第一筆轉換請求就噴 INITIALIZATION_FAILED,作者的回覆是請他安裝 X11 之類的顯示服務。這個細節值得注意:無頭伺服器上的問題不會在啟動階段暴露,而是到真的轉換才失敗。我本機能跑通,正是因為 macOS 桌面環境自帶 Aqua,剛好落在官方文件說的家用電腦與開發機情境。
換句話說,部署環境直接決定你要付多少錢:

| 版本 | 授權與價格 | 部署限制 |
|---|---|---|
| 社群版 | LGPL-3.0,免費(含商業使用) | 必須有顯示伺服器,無頭需另購 |
| 企業版 | 港幣 6,200 | 支援無頭 Docker,限內部伺服器 |
| 企業版 OEM | 港幣 10,199 | 允許嵌入、再散布或部署到第三方與雲端 |
| 評估版 | 免費下載 | 企業版功能全開,但輸出帶水印、僅限測試 |
價格與條款以 2026 年 8 月官網定價頁為準。兩個容易漏看的細節:每份授權只含一年維護(更新與技術支援),屆期要按當時價格續購,不續購不影響既有使用權;企業版 EULA 明定部署到雲端系統(條文列舉 AWS、Azure、Google Cloud、阿里雲、騰訊雲等)必須持有 OEM 授權。EULA 的準據法是中國大陸法律,爭議送鄭州仲裁委員會,這是採購前該知道的事實。
還有一條值得留意:EULA 裡寫著不得基於這套軟體開發、銷售或分發「具有類似功能的產品」。對要把它包進自己產品線的團隊來說,這種競業條款的存在本身就是決策變數。
官網首頁把內建 QRCode、Code128 等百餘種條碼與深度整合 ECharts 圖表當成主打特色列在最顯眼的位置,但沒有標注版本歸屬。對照文件就會發現:條碼用的 <barcode> 自訂標籤和圖表用的 <chart> 自訂標籤,都放在企業版文件分類下;什麼是 BKHTMLTOPDF 頁列出的僅企業版可用功能,也包含近百種條碼、一行標記就能嵌入這類描述。
有意思的地方在於,條碼與圖表靠的是自訂標籤的便利性,而不是引擎能力差異。社群版本身就是完整的 Chromium,會跑 JavaScript,你自己放 ECharts 的 JS 進去一樣能渲染出圖表,只是要自己寫,沒有那一行 <chart src="chart-1"> 的糖。企業版的條碼標籤用法長這樣,繼承 <img> 的屬性再加 type 與 value:
<barcode type="qrcode" value="Hi, bkhtmltopdf." width="200px" height="200px" />
<barcode type="code128" value="123456789" options="includetext" />
圖表標籤則是用 src 指向同頁面裡一段 JSON5 格式的 <script>,引擎支援 ECharts 與 Chart.js 兩種後端。判定方式很簡單:想要官方封裝好的條碼與圖表標籤、無頭部署與技術支援,就把它當商業軟體來評估;只想用引擎本身,社群版的授權允許自由使用,包括商業用途。
企業版另有一頁優勢說明:宣稱比社群版快 30% 到 50%、程序隔離、更新的 Chromium。這些我沒有購買授權無法驗證,就讓它停留在官方宣稱的位置。
讀它的原始碼會看到一個多數同類工具沒有的設計。HtmlToAnyService 在建立每個 Chromium client 時掛了請求過濾器:只放行 GET 與 OPTIONS,而且目標必須是 http、https,或自家暫存目錄裡的 file 協議檔案,其餘請求一律攔下。
我實際驗證過這個行為:在餵給它的 HTML 裡放一張指向本地測試伺服器的圖片,伺服器日誌收到了 GET;同一份 HTML 裡的 JavaScript 用 fetch 對同一台伺服器發 POST,日誌完全沒收到,請求在引擎層被擋掉了。這代表拿它處理不受信任的 HTML 時,頁面裡的腳本無法用 POST 把資料往外送。
不過白名單是雙面的:http 與 https 的 GET 是放行的。你餵給它的 HTML 若引用外部圖片、字型或腳本,服務主機就會真的去抓,包括內網位址。把這個服務架在內部網路時,等於多開了一個會替別人發 GET 請求的對外通道,輸入來源要自己把關。
看 GitHub 的時間線,這個專案的節奏很清楚:2025 年 10 月 6 日建立,六個 release 全部擠在 10 月到 11 月 26 日之間,之後 main 分支就沒有新的 commit。相依性更新機器人的提案從 2025 年 12 月起一件都沒被採用,多數還開著;2026 年 6 月還有使用者回報企業版 Docker 映像無法渲染的 issue #17,至今沒有回應。
付費線的狀況值得攤開看:issue #17 的啟動日誌顯示企業版映像跑的是 Spring Boot 3.5.6 與另一套版號(輸出類名做過混淆),和社群版儲存庫停在 Spring Boot 4.0.0、版號 0.0.6 的狀態確實分岔。不過查 Docker Hub 的映像推送紀錄,企業版映像最後一次更新停在 2025 年 10 月 22 日,比社群版 main 凍結得還早,兩條線實際上都沒有公開可見的更新。文件也有些漂移:系統需求頁寫 SpringBoot 3 與 Chromium 135 以上,實際 pom 是 4.0.0 與 141 系列。
另外,官網導覽列的線上體驗連向 demo.bkhtmltopdf.com,目前打開看到的是主機管理面板的「沒有找到網站」預設頁,線上 demo 實質上是掛的。想試的人直接下載 JAR 比較快。
如果團隊本身有 Node 環境,Playwright 或 Puppeteer 驅動無頭 Chromium 轉 PDF 是零授權費的路線;想要現成 Docker 服務的話,Gotenberg 也是免費開源。這幾條路都能做到無頭部署,BKHTMLTOPDF 的不可替代性集中在兩點:Java 團隊不用為了轉 PDF 多養一套 Node 工具鏈,一個 JAR 放進既有 JVM 生態就能用;以及它的授權模式是買斷制加一年支援,對不想自己維護 Chromium 版本升級的單位有吸引力。
判斷軸可以收斂成三個問題:你的部署目標有沒有顯示伺服器?沒有的話,無頭需求值不值港幣 6,200 起的授權費?你的 HTML 是否複雜到需要完整 Chromium 排版(若是,純後端函式庫如 openhtmltopdf 這類不跑 JavaScript 的方案就不適合)?
### 常見問題
社群版真的可以免費商用嗎?
可以。授權是 LGPL-3.0 與商業授權並存的雙授權,定價頁明寫社群版可用於個人專案、研究、開源專案或商業用途。限制在於:若修改後重新散布,修改部分要按 LGPL 公開;要靜態連結進閉源產品就該考慮商業授權。
部署在 AWS 或 GCP 上跑社群版違反授權嗎?
社群版走 LGPL,部署位置沒有額外限制。「部署到雲端必須買 OEM」那條寫在企業版 EULA 裡,約束的是企業版與評估版產品。評估版映像在雲端上跑已經落入 EULA 範圍,這點要分清楚。
它跟 wkhtmltopdf 是什麼關係?
沒有直接關係,但確實站在同一個需求上。wkhtmltopdf 用的是 Qt WebKit 引擎,專案 2023 年初封存(最後更新停在 2022 年 11 月),現代 CSS 支援停在老版本。BKHTMLTOPDF 的價值就是把這個需求換到會持續更新的 Chromium 引擎上,只是免費線的維護動能目前也停下來了。
轉換速度的官方數字可信嗎?
官方 10 頁 60 毫秒是 8 核心 Docker 環境的熱啟動平均,量測口徑官方沒有寫清楚;本機實測十頁約 0.2 秒是包含 HTTP 來回的時間。兩個數字各自描述不同的東西,官方數字我沒有辦法重現,本機數字是實測。
在 Mac 或 Windows 桌機上可以直接用嗎?
可以,這正是社群版設定的使用情境。macOS 的 Aqua 與 Windows 桌面本身就是顯示伺服器,我在 macOS 上從下載到產出第一份 PDF 沒有做任何額外設定。會踩到限制的是無桌面的 Linux 伺服器。
大檔案或複雜文件有什麼上限?
檔案上傳(multipart)的單次請求上限 32MB,列印逾時預設 15 秒、可在請求參數裡調整。官方效能頁標示千頁文件約 2 秒完成,但那是它們的 Docker 環境;實務上文件越大、外部資源越多,等待條件的設定就越重要。
適合的情境相當明確:Java 或 Spring 技術棧的團隊、要在有桌面環境的機器上先驗證文件產製流程、中文文件需要字型內嵌、想用一個 JAR 一次解決、不想再組合多個工具。發票、請款單、報表、票券這類「HTML 模板加資料」的場景正是它的主場,官方最佳實踐文件也是拿入場券和發票當範例。
反過來說,已經有成熟 Node 工具鏈的團隊、只想偶爾轉幾份網頁存檔的人(線上工具如 Webtopdf 這類網頁轉 PDF 服務更省事)、以及需要立刻部署到無頭雲端又不想付授權費的單位,免費替代路線都更合理。想在命令列處理 PDF 內容的,Nano PDF 這類命令列 PDF 工具和講求本地處理的 Secure PDF Editor 塗黑工具是不同環節的選擇;文件產製鏈上前後端的工具,像 docmd 把 Markdown 變文件網站、Firecrawl PDF Inspector 判斷 PDF 要不要 OCR,可以跟它拼成完整管線。
下一步很單純:從 GitHub Release 下載社群版 JAR,拿你自己最常輸出的那份文件模板(發票、月結報表都行)餵給它,看排版與速度能不能過你自己的關。本機驗證通過後,再回頭決定部署環境與要不要走企業版授權,這個順序可以避免先付了錢才發現模板排不出來。
社群版採 LGPL-3.0,與商業授權並存(LICENSE 檔開頭就寫明雙授權,商業洽詢指向定價頁),GitHub 上 235 顆星、13 個 fork,由單一開發者維護,main 分支最後 commit 停在 2025 年 11 月 26 日(v0.0.6)。六個 release 全部集中在 2025 年 10 月到 11 月,之後免費線就沒有再動過。企業版閉源、僅以 Docker 映像發布,港幣 6,200 與 10,199 兩級授權各含一年維護,到期續購才有更新與支援。
採用前建議把三份文件一起看:LICENSE 檔的雙授權條款、定價頁的維護續購說明、EULA 的部署與準據法條文。這三份講的是不同的事,任一份單獨看都會漏掉邊界。官方文件與定價以 bkhtmltopdf.com 現況為準,這類單人專案的條款與價格變動通常不會有提前公告。