(詳細)CentOS 7+環境下PHP使用Imagick+ghostscript將PDF文件轉爲圖片

如題,博主今天遇到個業務問題,需要對用戶上傳的PDF文件轉png操作,其實就是個首頁預覽功能,不細說了。

首先,作爲一個懶人,遇到新的問題我首先想的是這個坑我還是不親自去踩了,機制的google了一發,發現很多人寫的教程,大喜。前人艱難填坑後人一路坦途,但是理想和現實總是有差距的,各個博主衆說紛紜,還有好幾年前的過期博文,按他們鋪的路走差點沒把自己埋坑裏。不得已又自己來踩坑了,我儘量把我的過程寫的詳細,爲後人提供參考,但是我懶,233333,你們懂得。


對於什麼是Imagick大家可能比較陌生,但是ImageMagick大家說不定還是有點了解的,imagick其實就是ImageMagick的php擴展,有非官方說法:Imagick的新能比GD要優越不少,博主比較懶,就沒去具體測試了,有興趣的同學可以自己研究一下。


相關地址集合:

php官方文檔: http://php.net/manual/en/book.imagick.php

ghostscript官網: https://www.ghostscript.com

ImageMagick官方下載地址:https://sourceforge.net/projects/imagemagick/files/

imagick函數中文解釋:http://www.jb51.net/article/60161.htm

前提:你會編譯安裝php,服務器安裝了c++、gcc-c++等基本庫



1 安裝ImageMagick

博主通過不爲人知的“骯髒”手段拿到了下載地址,直接在服務器上下載了源碼包:

下載地址: https://netix.dl.sourceforge.net/project/imagemagick/im7-src/ImageMagick-7.0.7-25.tar.gz

下載命令:

wget https://netix.dl.sourceforge.net/project/imagemagick/im7-src/ImageMagick-7.0.7-25.tar.gz


運行截圖如下,我先進入了/home/app目錄下,所以文件也下載在這裏


下載完成後使用下面的命令解壓:

 tar -zxvf ImageMagick-7.0.7-25.tar.gz 

解壓完畢後進入該文件夾:

執行命令(默認參數,沒有更改)

 ./configure 

執行完了後如下圖所示,默認安裝路徑在/usr/local下


執行命令,編譯並安裝ImageMagick,需要一段時間,不如先來一局農藥壓壓驚。或者你可以另開一個terminal連接服務器開始安裝別的東西。

 make && make install


完成之後進入安裝文件夾,查看ImageMagick是否工作

 cd /usr/local/bin/

 ./convert -version

結果如下:


2 安裝PHP擴展Imagick.so

很遺憾,這不是php官方的標準包,所以沒有繼承在php源碼包裏面,我在ext/文件夾下沒有找到,不過官方文檔給出了下載頁面地址:

http://pecl.php.net/package/imagick/download

然而機智的我又直接把擴展包的下載地址貼上來了,方便服務器下載:http://pecl.php.net/get/imagick-3.4.3.tgz

我很懶,命令行在圖裏,同學自己看了==


解壓後進入該目錄,執行phpize,我希望你能找到你的phpize在哪,如果你是編譯安裝的話,如果沒有軟鏈到/usr/bin/目錄下,你可以使用絕對路徑調用phpize。使用下面命令行配置擴展安裝,指定--with-php-config是爲了統一管理我的extension.so,如果不指定,你也可以copy到php.ini指定的extension位置,--with-imagick默認是/usr/local如果你沒改動的話。

./configure --with-php-config=/usr/local/php7/bin/php-config --with-imagick=/usr/local




配置完成後 編譯安裝,是的,又是 make && make install

這些路徑很重要,有時候自己清楚點比較好

安裝完了後我們要修改php的配置文件,添加上imagick.so,重啓php-fpm


修改配置文件,記得保存


kill php-fpm主進程 並 重啓,這裏各個人方法不同,我按我的演示一下:


重啓完了看看自己的phpinfo吧,已經有了


這個時候我們試試pdf轉png


以失敗告終,控制檯的測試都失敗了別說用php的系統調用了,一樣gg,大部分國內博客的教程基本到此爲止,然後就開始貼代碼了,我特麼就想噴一句,代碼格式都亂七八糟的,到底是你寫的還是copy的?關鍵時候還是overstack靠譜。看上面截圖提示的錯誤信息:

convert: FailedToExecuteCommand `'gs' -sstdout=%stderr -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=2 '-sDEVICE=pngalpha' -dTextAlphaBits=4 -dGraphicsAlphaBits=4 '-r72x72'  '-sOutputFile=/tmp/magick-26757KhSit2bKyfwa%d' '-f/tmp/magick-26757lL6cdz2j5VDZ' '-f/tmp/magick-26757SnLQ7f7amJLO'' (1) @ error/pdf.c/InvokePDFDelegate/291.

convert: no images defined `%d.png' @ error/convert.c/ConvertImageCommand/3275.


帶有gs 開頭的命令行執行失敗,gs其實就是下面要說的ghostscript


3 安裝GhostScript 

官方地址:https://www.ghostscript.com/

使用教程:https://www.ghostscript.com/doc/9.22/Use.htm

官方安裝教程: https://www.ghostscript.com/doc/9.22/Install.htm

下載地址: https://www.ghostscript.com/download/gsdnld.html

博主比較懶,不想編譯安裝了,直接下載了編譯後的可執行程序,能有就行,23333

我選的是這個,看起來是免費的屌絲版,能用就行,233333


這個下載地址被重定向了好多次,沒法直接給你們貼上,不過我傳到了我的七牛雲上,地址給大家共享下:

https://file.mumov.com/ghostscript-9.22-linux-x86_64.tgz

下載到服務器,解壓,進入文件夾:


完了之後記得給gs的可執行文件copy一份到/usr/bin目錄下,這樣就可以全局執行了

命令行在圖裏,懶,不寫了

到這裏基本上就完成了所有模塊的安裝,試試pdf轉png行不行


很好,沒有報錯,轉成了png圖片了,下面終於可以寫代碼了


4 PHP代碼實現pdf轉圖片

我懶,原諒我直接貼代碼了


class ImageMagick{


    private $handler;
    public function __construct()
    {
        $this->handler = new \Imagick();
    }

    /**將pdf轉爲png圖片列表
     * @param $pdf_path string pdf文件的絕對路徑
     * @param $out_path string 生成圖片存放位置的絕對路徑
     * @param int $from int  從第幾頁開始轉
     * @param int $to int 截止於第幾頁
     * @return array
     * @throws SystemInnerException
     */
    public function convertPdf2Images($pdf_path,$out_path,$from=1,$to=1)
    {
        $this->handler->setResolution(120,120);
        $this->handler->setCompressionQuality(50);
        $this->handler->readImage($pdf_path);
        $pages = count($this->handler);
        if($pages == 0)
            throw new SystemInnerException('empty pdf file!');
        $index = 1;

        $data = [];
        foreach ($this->handler as $k=>$v)
        {
            if($index == $from)
            {
                if($from<=$to) {


                    $v->setImageFormat('jpg');
                    $tmp_name = str_random('16') . '.jpg';
                    if ($v->writeImage($out_path.$tmp_name) == true)
                        $data[] = $tmp_name;
                    $index++;
                    $from++;
                }else
                    break;
            }else
                $index++;
        }

        return $data;
    }
}
好了,到這裏結束了,博主自認爲寫的比其他的可能要清除那麼一丟丟,如果有疑問,歡迎留言噴我,23333


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章