最近應(yīng)業(yè)務(wù)需要余舶,需要實(shí)現(xiàn)在線瀏覽 PPT啊鸭、PDF 的功能。搜了一陣匿值,看似好用的微軟 Office Web Viewer 卻有著速度極慢赠制、限制10M大小等麻煩,前端直接使用 pdf.js 也遇到了跨域之類的問題挟憔,索性一不做二不休钟些,把 PPT 和 PDF 都轉(zhuǎn)換成圖片,再分頁傳回給前端绊谭。
去網(wǎng)上搜了一圈政恍,看到了 imagick 這個(gè)擴(kuò)展庫,看了操作好像也是十分地簡單达传,沒想到真的動手做起來遇到了不少的麻煩篙耗。
首先是網(wǎng)上的版本迫筑,即用 PHP 的擴(kuò)展庫 imagick 來實(shí)現(xiàn)。
第一步是要安裝宗弯,我用的是寶塔面板脯燃,在 PHP 的安裝擴(kuò)展中找到了 imagemagick,一鍵安裝蒙保,并沒有再遇到什么問題辕棚,直接就能使用了。后來發(fā)現(xiàn)不少人手動安裝時(shí)遇到了許多問題追他,好像是因?yàn)?ImageMagick 需要 Ghostscript 的支持坟募,后面我也裝了一遍,確實(shí)挺麻煩的邑狸,這里記錄一下我的安裝過程:
我的系統(tǒng)是 CentOS7 的懈糯,在這個(gè)網(wǎng)址下載——https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/download/gs923/ghostscript-9.23.tar.gz
上傳到服務(wù)器進(jìn)行解壓,然后安裝单雾;或者直接通過命令行下載安裝(比較慢)赚哗,輸入gs --version 查看是否成功安裝。
//編譯安裝
# wget -c https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/download/gs923/ghostscript-9.23.tar.gz
# tar xzvf ghostscript-9.23.tar.gz
# cd ghostscript-9.23
# ./configure && make && make install
//直接yum安裝
yum -y install ghostscrip
之后是安裝 ImageMagick 和 imagick硅堆,這里因?yàn)槲沂菍毸苯友b的屿储,沒有手動安裝過,不知道還有沒有坑渐逃。另外够掠,裝完 imagick 之后還需要在 php.ini 中開啟相應(yīng)的擴(kuò)展。
//編譯安裝ImageMagick
# tar xf ImageMagick-6.8.9-9.tar.gz
# cd ImageMagick-6.8.9-9
# ./configure --prefix=/usr/local/imagemagick
# make && make install
//直接yum安裝
# yum install ImageMagick
//編譯安裝imagick
# tar -xf imagick-3.2.0RC1.tgz
# cd imagick-3.2.0RC1
# /usr/local/php/bin/phpize
# ./configure --with-php-config=/usr/local/php/bin/php-config --with-imagick=/usr/local/imagemagick
# make && make install
環(huán)境真是開發(fā)過程中最大的敵人茄菊,僅僅只是想把 pdf 轉(zhuǎn)成圖片這么個(gè)小操作疯潭,就得安裝三個(gè)東西,真是麻煩的很面殖。光顧著安裝了竖哩,還不知道這三個(gè)分別是啥呢。這三個(gè)當(dāng)中最核心的是 ImageMagick脊僚,它是第三方的圖片處理軟件相叁,功能強(qiáng)大,可以理解為命令行版本的PS辽幌。然后是 imagick增淹,是php的一個(gè)擴(kuò)展模塊,可以調(diào)用 ImageMagick 提供的API來進(jìn)行圖片操作舶衬。最后是 Ghostscript埠通,是一款可以操作 pdf 的軟件,在這里 ImageMagick 無法直接實(shí)現(xiàn) pdf 文檔到圖片的轉(zhuǎn)換逛犹,需要借助于 Ghostscript 軟件包端辱。
總算差不多了梁剔,終于能夠進(jìn)行開發(fā)了。本以為應(yīng)該很容易就能實(shí)現(xiàn)舞蔽,沒想到踩坑之路才剛剛開始荣病。首先先貼一段根據(jù)網(wǎng)上的代碼修改的代碼。
public function pdfToPng($pdf,$path,$page=-1) {
? ? if (!extension_loaded('imagick') || !file_exists($pdf) || !is_readable($pdf)) {
? ? ? ? return ['ok' => FALSE, 'msg' => '服務(wù)器錯(cuò)誤', 'code' => 2003, 'data' => []];
? ? }
? ? $im = new \Imagick();
? ? //設(shè)置分辨率
? ? $im->setResolution(150, 150);
? ? //設(shè)置壓縮質(zhì)量渗柿,1-100,100為最高
? ? $im->setCompressionQuality(100);
? ? //是否進(jìn)行分頁操作
? ? if ($page == -1) {
? ? ? ? $im->readImage($pdf);
? ? } else {
? ? ? ? $im->readImage($pdf . "[" . $page . "]");
? ? }
? ? foreach ($im as $Key => $Var) {
? ? ? ? //設(shè)置圖片格式
? ? ? ? $Var->setImageFormat('png');
? ? ? ? $filename = $path . md5($Key . time()) . '.png';
? ? ? ? if ($Var->writeImage($filename) == true) {
? ? ? ? ? ? $Return[] = $filename;
? ? ? ? }
? ? }
? ? return $Return;
}
核心代碼其實(shí)很簡單个盆,先實(shí)例化 Imagick 類,然后進(jìn)行一些相應(yīng)的設(shè)置朵栖,最后再通過 writeImage 導(dǎo)出為圖片颊亮。接下來看看效果(第一張為圖片,第二章為原PDF)
一開始我眼瞎陨溅,以為這個(gè)庫只能做到讀取 PDF 中的圖片终惑,文字并不能讀取到。在漫長的百度過程中又把 png 格式改成了 jpg门扇,中間又出現(xiàn)了些奇怪的黑色區(qū)域雹有。后來無意中按出 F12 加上仔細(xì)觀察才發(fā)現(xiàn),原來文字并沒有顯示出來的原因是背景為透明的臼寄。
找到問題之后霸奕,目標(biāo)變得明確了——把背景搞白!在又一陣搜索之后吉拳,找到了一個(gè)廢棄的方法 flattenImages质帅,但是很可惜,它已經(jīng)被官方棄用了留攒,并且沒有明確地說用哪個(gè)函數(shù)代替它临梗。即使這樣,還是不能氣餒稼跳,去搜了搜 它,大概了解到它的功能——合并圖層吃沪!沒錯(cuò)汤善,把我們之前的結(jié)果和一個(gè)空白圖層合并,不就能達(dá)到把背景變成白色的效果了嗎票彪!按照這種思路红淡,繼續(xù)搜索,終于找到了降铸!這里貼一下核心代碼在旱,只需要修改之前代碼中的 foreach 循環(huán)中的內(nèi)容就夠了。
$blankPage = new \Imagick();
//一張白紙推掸,作為背景
$blankPage->newPseudoImage($item->getImageWidth(), $item->getImageHeight(), "canvas:white");
//設(shè)置合并的位置
$blankPage->compositeImage($item, \Imagick::COMPOSITE_ATOP, 0, 0);
//合并桶蝎!
$blankPage = $blankPage->mergeImageLayers(\Imagick::LAYERMETHOD_FLATTEN);
$filename = str_replace('.pdf', '-' . $key . '.jpg', $pdfStr);
if ($blankPage->writeImage($filename) == true) {
? ? $result[] = $filename;
}
果不其然驻仅,白色的背景來了!但是就在我歡呼雀躍登渣,想著終于把問題解決了的時(shí)候噪服,又發(fā)現(xiàn)了一點(diǎn)不對勁,這圖片失真也太嚴(yán)重了吧胜茧!稍微放大一點(diǎn)都模糊得不行了粘优。本以為這應(yīng)該不是什么問題,只需要改一改之前提過的分辨率和壓縮質(zhì)量呻顽,結(jié)果發(fā)現(xiàn)雹顺,不論怎么改圖片的分辨率都沒有半點(diǎn)變化。
雖說至此廊遍,問題已經(jīng)勉勉強(qiáng)強(qiáng)地解決了嬉愧,但是這個(gè)分辨率是個(gè)硬傷,肯定不能放著不管昧碉。又在一頓瘋狂的搜索之后英染,我仍然沒能解決,終于被饿,我敗給了時(shí)間四康,放棄了這條路。但于此同時(shí)狭握,一條光明大道逐漸在我眼前明亮起來闪金。之前也提到過,imagick 只是把 ImageMagick 的命令封裝了一下給 PHP 使用而已论颅,那我索性直接繞過 imagick哎垦,直接執(zhí)行 ImageMagick 命令不就好了?一頓操作之后恃疯,果然漏设,成了,終于成了今妄。
$command = 'convert -density 150 -background white -alpha remove '.$pdfStr.' '.str_replace('.pdf', '.jpg',$pdfStr);exec($command);
稍微解釋一下吧郑口,-density 150 指定輸出的分辨率,越大越清晰盾鳞,但是文件也會相應(yīng)地變大犬性。
-background white -alpha remove可以一次命令轉(zhuǎn)換多頁 PDF 成多個(gè)圖片并保持白色背景。
后面兩個(gè)參數(shù)分別是需要被轉(zhuǎn)換的 pdf 文件地址和轉(zhuǎn)成的圖片名腾仅,比如像我這樣寫乒裆,能夠把兩頁的 pdf 文件1.pdf 轉(zhuǎn)成1-0.jpg 和 1-1.jpg 。
接下來是 PPT 轉(zhuǎn)圖片推励。這里要利用 Linux 下的另一個(gè)工具:unoconv鹤耍。unoconv肉迫,全稱為?Universal Office Converter ,是一個(gè)命令行工具惰蜜,可在 LibreOffice/OpenOffice 支持的任意文件格式之間進(jìn)行轉(zhuǎn)換昂拂。
首先是安裝:我的系統(tǒng)是 CentOS7 的,如果是別的系統(tǒng)不適用的話抛猖,還得再去百度一下格侯。
1、安裝libreoffice:
yum install -y libreoffice.x86_64
2财著、下載或者克隆unoconv:
wget https://github.com/unoconv/unoconv/archive/master.zip
3联四、解壓并安裝:
unzip master.zip
cd unoconv-master/
make install
就這樣簡簡單單的三步,unoconv 就安裝完了撑教。unoconv 的使用也非常的簡單朝墩,舉一個(gè)最簡單的例子:
unoconv -f new.pdf old.ppt
雖然轉(zhuǎn)換十分的簡單,只需要一個(gè)指令伟姐,但是這里還有一個(gè)隱藏的小坑——Linux 下和 Windows 下的字體文件不同收苏,很多 Windows 有但是 Linux 并沒有,這就會導(dǎo)致轉(zhuǎn)換之后出現(xiàn)文字亂碼愤兵、排版出錯(cuò)等問題鹿霸,解決方案就是,把 Windows 下的字體拷一份到 Linux 下秆乳。
1懦鼠、找到Windows下的這個(gè)目錄:C:\Windows\Fonts,把里面的文件拷到Linux下的/usr/share/fonts/ 下屹堰,最好新建一個(gè)目錄肛冶,再放在里面,方便管理扯键。
2睦袖、進(jìn)入目錄,執(zhí)行指令荣刑,比如說我新建的目錄叫win
cd /usr/share/fonts/win
mkfontscale
mkfontdir? ? ? ? ? ? //這兩條命令是生成字體的索引信息
fc-cache -fv? ? ? ? //更新字體緩存
安裝好字體之后扣泊,再執(zhí)行一次轉(zhuǎn)換指令,應(yīng)該不會有什么大問題了嘶摊。
另外,如果你有興趣评矩,或者是有問題想要與我探討叶堆,歡迎來訪問我的博客:https:mu-mu.cn/blog