1. 程式人生 > >PHP生成PDF並轉換成圖片爬過的坑

PHP生成PDF並轉換成圖片爬過的坑

  需求描述:根據訂單通過模板合同生成新的PDF合同通過e籤寶簽約後轉為圖片給使用者下載。

  需求整理:

    1.如何生成PDF檔案:使用TCPDF擴充套件生成。思考:

      ⑴為了方便將模板中的固定佔位符替換為訂單中的內容,使用靜態html頁面儲存合同模板的方式儲存

      ⑵使用TCPDF將html轉換為pdf文件,可以儘量保證合同格式的一致性

    2.將生成的PDF合同通過e籤寶的簽約流程進行圖章簽署。具體流程忽略:對比e籤寶簽約流程

    3.將簽約後的新PDF合同轉換為圖片。思考:

      ⑴使用php的Imagick擴充套件實現(坑之所在)

 

  實現流程:

    1.安裝TCPDF擴充套件,這個都是原生的PHP程式碼庫比較簡單,依賴composer。在要安裝的目錄命令列直接敲:

composer require smalot/pdfparser

    2.安裝Imagick擴充套件,這個流程比較多。可以參考下面連結(感謝感謝):

    https://www.cnblogs.com/jinxiblog/p/8053008.html  --windows環境安裝(我是windows開發環境,使用這個沒毛病)

    https://www.osyunwei.com/archives/5327.html    --linux環境安裝(沒測試過,留給以後測試)

    https://blog.csdn.net/webben/article/details/64125470    --linux環境安裝(沒測試過,留給以後測試)

    3.第一個坑,Imagick裝好就行了嗎?並不然,網上找了很多資料後表面Imagick的執行機制大概是php通過Imagick擴充套件呼叫本機安裝的Imagemagic提供的介面來處理圖片,另外如果你要readImage的是一個PDF檔案那麼還有一個前提就是Imagemagic應用本身還會呼叫ghostscript這個玩意。

因為我們的需求是將PDF轉換為圖片而不是普通的圖片檔案處理,所以ghostscript也是我們必須要安裝的。linux下同理。如果沒安裝的話會出現諸如下面的錯誤:

 

Postscript delegate failed `/Uploads/Download/2016-09/57d0fb5b3612d.pdf': No such file or directory @ error/pdf.c/ReadPDFImage/664

 

  看看Imagick下面官方說明:

 

    4.安裝ghostscript,官網上根據自己的環境下載不同安裝包,如果phpinfo()中的php是X86的話記得要選32位的安裝包下載,裝完後記得重啟。本人重啟了n次才突然間成功

    https://www.ghostscript.com/download.html    --下載連結

 

    5.到這裡基本的依賴已經安裝完畢,貼下本地實驗程式碼如下:

 

require_once 'vendor/autoload.php';

//PDF檔案生成 $tcpdf = new TCPDF(); $tcpdf->SetCreator('Hello'); $tcpdf->SetAuthor('walter'); $tcpdf->SetTitle('test pdf'); $tcpdf->SetSubject('subject'); $tcpdf->SetKeywords('walter,pdf,php'); $tcpdf->setHeaderData('logo_example.png',20,'標題','子標題',array(0,64,255),array(0,64,128)); $tcpdf->setFooterData(array(0,64,0),array(0,64,128)); $tcpdf->setHeaderFont(['stsongstdlight', '', '10']);    //設定字型 $tcpdf->setFooterFont(['helvetica', '', '8']);       //設定字型  $tcpdf->SetDefaultMonospacedFont('courier');        //設定字型 $tcpdf->SetMargins(15,27,15); $tcpdf->setHeaderMargin(5); $tcpdf->setFooterMargin(10); $tcpdf->SetAutoPageBreak(true,25); $tcpdf->setImageScale(1.25); $tcpdf->setFontSubsetting(true); $tcpdf->SetFont('stsongstdlight','',14);    //設定字型 // $tcpdf->AddPage(); $html = file_get_contents('contract.html'); $tcpdf->writeHTMLCell(0,0,'','',$html,0,1,0,true,'',true);    //寫入html $tcpdf->Output(__DIR__.DIRECTORY_SEPARATOR.'contract.pdf','F');  //生成pdf檔案並儲存到本地 //pdf合併轉換一張圖片 function pdf2png($from_path,$target_path){ try{ $img = new Imagick(); $img->setCompressionQuality(100); $img->setResolution(120,120); $img->readImage($from_path); $canvas = new Imagick(); $imgNum = $img->getNumberImages(); foreach ($img as $k => $sub){ $sub->setImageFormat('png'); $sub->stripImage(); $sub->trimImage(0); $width = $sub->getImageWidth() + 10; $height = $sub->getImageHeight() + 10; if ($k + 1 == $imgNum) $height += 10; $canvas->newImage($width,$height,new ImagickPixel('white')); $canvas->compositeImage($sub,Imagick::COMPOSITE_DEFAULT,5,5); } $canvas->resetIterator(); $canvas->appendImages(true)->writeImage($target_path); return true; }catch (Exception $e){ echo $e->getMessage(); echo $e->getTraceAsString(); return false; } //pdf檔案轉換為一張圖片 $pdf_path = __DIR__.DIRECTORY_SEPARATOR.'contract.pdf'; if (is_file($pdf_path)){ var_dump(pdf2png($pdf_path,__DIR__.DIRECTORY_SEPARATOR.'contract.png')); }else{ echo 'file not exist'; }

 

  

 

    至此本地測試沒毛病一切OK

             PDF檔案                                  生成的圖片         

    

    6.正式伺服器上測試(最大的坑來了),生成PDF檔案一切OK,到了轉換圖片的時候就:

      

    一遍空白!!!!!!神坑

    一遍度娘亂七八糟的資料後發現根本沒有這方面的資料。偶爾在百度提問裡面看到有人又類似說法是,Imagick->readImage的時候中文編碼的問題。雖然不太對但是在萬能的stackoverflow有人提過類似的問題

    

    經過不停的踩坑發現是ghostscript這個坑貨的問題,在linux下安裝ghostscript的時候沒有對應生成cidfmap檔案來支援各種字型,在windows環境安裝的時候已經在lib目錄下面生成了這個配置檔案。所以需要在linux環境下新建一個cidfmap檔案並且將我們要支援的字型放到linux下來:

    http://www.voidcn.com/article/p-fdqtdali-rx.html     --參考連結

 

    這樣就行了嗎?還沒有.......看看程式碼裡面我生成pdf時設定了什麼字型?這些是adobe公司預設的字型,但是比較不統一。你程式碼裡面要設什麼字型就得把對應的ttf字型檔案放到linux下重新對應cidfmap的字型格式設定一遍。

$tcpdf->SetFont('stsongstdlight','',14);
$tcpdf->setHeaderFont(['stsongstdlight', '', '10']);
$tcpdf->setFooterFont(['helvetica', '', '8']);

$tcpdf->SetDefaultMonospacedFont('courier');

 

  為了避免麻煩我在windows的字型庫裡面拿了一個simhei字型(簡體字)放到linux下配置好,最後發現這個字型不是TCPDF擴充套件內建的(坑)。還好tcpdf庫提供了一個新增字型的指令碼,具體路徑如下:

 

    把要新增的simhei字型放進來命令列輸入如下命令:

 

#\tools>php ./tcpdf_addfont.php -b -i simhei.ttf

>>> Converting fonts for TCPDF:
*** Output dir set to D:\phpStudy2016\WWW\mugua\muguaadmin\public\task\pdf\vendo
r\tecnickcom\tcpdf/fonts/
+++ OK   : D:\phpStudy2016\WWW\mugua\muguaadmin\public\task\pdf\vendor\tecnickco
m\tcpdf\tools\simhei.ttf added as simhei
>>> Process successfully completed!

 

 

 

 恭喜你,爬坑完畢字型終於可以正常使用,生成的圖片再也不是空白了