Slim PHP Print HTML to PDF By Chrome
最近剛好遇到了需要提供下載PDF的案子,之前的做法是透過TCPDF 這個套件處理,
有機會再分享實作的方法,而這次要分享的,則是使用chrome 的語法將寫好的html 內容轉成PDF。
會想要使用chrome 來執行,是因為大多數的電腦都有裝chrome,在server上要裝chrome 也很容易,
相信許多MIS都不會介意在自己家主機裝chrome,所以就嘗試了這個方法,也將遇到的雷點記錄下來,希望大家可以避免。
寫在前面
開發使用php slim framework,透過php dev server 執行專案(php -S 0.0.0.0:port<-雷點在此,稍後說明)。
正文
要使用chrome 來執行將html 轉成 pdf,先提供幾個關鍵字:
- chrome cmd
- chrome headless command
- chrome print-to-pdf
- php exec()
大致上來說,我們希望透過chrome.exe 來執行一段chrome 的指令,將已經寫好的html 轉存成pdf,
再透過給定的 http response header 來產出的pdf 以附件的方式回傳到瀏覽器,瀏覽器就會執行下載了。
首先我們要先知道chrome.exe 的絕對路徑,或者是將其設定環境變數,為了Demo 方便,就直接給定絕對路徑,請依實際情況修改:
1 | $chrome_path = "C:\Program Files\Google\Chrome\Application\chrome.exe"; |
再來須指定chrome 匯出pdf 後要存到哪裡:
1 | // 我先設定好一個常數,指定了pdf 存的路徑 |
接著來看到chrome 的指令
1 | $command = "\"{$chrome_path}\" --headless --disable-gpu --print-to-pdf=\"{$outputFile}\" https://google.com 2>&1" |
簡單來看,我們不希望真的開起瀏覽器來做這件事情,而是希望在背景執行,並且將目標網頁的html 轉成pdf,放到我們指定的地方。
接著就是要執行這段我們已經打好的command了
1 | $output = null; |
exec() 這個方法有三個參數,第一個為必要,後面兩個為選填,為了Debug 方便所以這邊三個參數都有用到。
執行完後會將輸出及結果分別放到這兩個指定參數中,這樣就可以知道哪裡出錯了。
執行到這邊,應該就可以看到我們指定的路徑已經有pdf 的檔案了。最後的步驟就是將檔案回傳到瀏覽器供下載,
這邊我使用的是Slim Psr7 中的Factory,將串流回傳出去。
1 | $stream = (new StreamFactory())->createStreamFromFile($output_file); |
就算你使用的不是slim 框架,應該也能找到相對應的方法,將pdf 檔案傳出去。
接著我們透過瀏覽器,開啟這個頁面,馬上就可以下載一份名為Chrome.pdf 的檔案,內容如圖
這樣就完成了這次的 html 轉 pdf 的功能了!
雷點
上面有稍微提示雷點是透過php dev server 來執行我的專案,
一開始我是透過此方法來執行專案,會發現執行我們寫好的command,網頁就會進入pending狀態,
就算把chrome 關掉,把監聽專案的php dev server中斷都沒有用,
只能透過工作管理員,將卡住的chrome 結束工作。
我試著將 –headless 拿掉,這時會開啟預設瀏覽器,並跳轉到我們要輸出的url (https://google.com),
但是完全沒有產出pdf 檔案,也找不到問題點。
後來先將專案上傳到server,是透過Apache 來執行專案,突然發現功能一切都正常,pdf 也正常產出,
瀏覽器也可以正確下載到這個檔案,搞了半天找不出答案的問題突然就解開了,我目前還沒有找到原因,
若你有任何相關的資訊,歡迎與我分享!