一.問題描述php
須要用php把html生成pdf,找了了個php擴展,HTML2PDF,只能生成一些簡單的HTML代碼,複雜的HTML+css沒法生成。網上找到了強大的wkhtmltopdf。css
二.wkhtmltopdf介紹html
工具全名叫 "wkhtmltopdf" ; 是一個使用 Qt WebKit 引擎作渲染的,可以把html 文檔轉換成 pdf 文檔 或 圖片(image) 的命令行工具。(強調一下:是 「命令行工具」 )支持多個平臺,可在win,linux,os x 等系統下運行。linux
三.wkhtmltopdf安裝(linux環境)shell
安裝步驟很簡單,我在這裏就不贅述了,具體能夠參照(https://blog.csdn.net/assasin...://blog.csdn.net/qq_26562641/article/details/72875344),裏面寫的都很詳細瀏覽器
問題1:測試後發現,生成的pdf文件對中文並不支持(外國人寫的軟件,這個沒辦法)? 答案:自行下載中文字體,安裝在linux的字體庫,具體方法能夠參照(https://yq.aliyun.com/ziliao/269854)進行操做,其中字體能夠在此網站下載(http://www.font5.com.cn/font_download.php?id=150&part=1237886897) ***下面是重點戲!!!!!!!***
三.php操做wkhtmltopdf緩存
方法:1.一個是exec執行 2.擴展包操做(建議採用,本文介紹的就是這個方法,因爲咱們是採用php語言開發,因此我在composer中選用了 mikehaertl/phpwkhtmltopdf包)
四.mikehaertl/phpwkhtmltopdf包的具體使用服務器
1.包的安裝(composer很方便)composer
2.具體使用能夠參照該包的使用說明socket
3.使用中出現的問題:
q.在本地環境測試能夠正常的下載,可是在linux環境下卻不行? a.php.ini的禁用函數 proc_open()要去除,若是不行(將禁用函數去除) q.php.ini中的禁用函數去除後,仍是不行,槽糕的是,把服務器搞的沒法訪問(解決辦法:清除瀏覽器緩存)? a.說的這個問題,咱們來科普一下proc_open()---php內置函數 proc_open():執行一個命令,而且打開用來輸入/輸出的文件指針。 wkhtmltopdf使用該命令,來進行pdf文件的生成&寫入工做(生成&寫入基於管道命令),因此在輸入&輸出有一方出現問題,就會致使,該管道沒法關閉,從而出現管道阻塞,從而致使宕機。見代碼(取自:vendor/mikehaertl/php-shellcommand/Command.php文件總的execute方法片斷): $process = proc_open($command, $descriptors, $pipes, $this->procCwd, $this->procEnv, $this->procOptions); if (is_resource($process)) { if ($this->_stdIn!==null) { if (is_resource($this->_stdIn) && in_array(get_resource_type($this->_stdIn), array('file', 'stream'), true)) { stream_copy_to_stream($this->_stdIn, $pipes[0]); } else { fwrite($pipes[0], $this->_stdIn); } fclose($pipes[0]); } $this->_stdOut = stream_get_contents($pipes[1]); $this->_stdErr = stream_get_contents($pipes[2]); fclose($pipes[1]); fclose($pipes[2]); $this->_exitCode = proc_close($process); if ($this->_exitCode!==0) { $this->_error = $this->_stdErr ? $this->_stdErr : "Failed without error message: $command"; return false; } } else { $this->_error = "Could not run command $command"; return false; } 代碼中的$descriptors,規定了包含了要傳送至進程的管道的描述信息。 第一個元素爲描述符類型, 第二個元素是針對該描述符的選項。 有效的類型有:pipe (第二個元素能夠是: r 向進程傳送該管道的讀取端,w 向進程傳送該管道的寫入端), 以及 file(第二個元素爲文件名)。
表達一個真實文件描述符的流資源類型 (例如:已打開的文件,一個 socket 端口,STDIN)。
而我在實際調試中卻發現,我在本地調試時,該參數寫入端爲w,而linux中寫入端爲r,這個是宕機的罪魁禍首。進行代碼分析: $descriptors = array( 1 => array('pipe','w'), 2 => array('pipe', $this->getIsWindows() ? 'a' : 'w'), ); public function getIsWindows() { return strncasecmp(PHP_OS, 'WIN', 3)===0; } 將 2 => array('pipe', $this->getIsWindows() ? 'a' : 'w'),=》修改成 2 => array('pipe', 'a'),問題解決。