设为首页 收藏本站
查看: 464|回复: 0

[经验分享] php中网页生成图片的方式,类似长微博图片生成器

[复制链接]

尚未签到

发表于 2017-4-13 08:07:16 | 显示全部楼层 |阅读模式
  导读:因媒体站微博传播需要,需在转发文章至新浪微博时能将文章正文已图片形式传播出去,用以提高微博内容转发积极性,顾需要在原有php项目代码中加入网页转图片功能。
  在java中网页转图片有已经开源的转换工具,较为简单,php中网页转图片的开源工具很少,少到只有一个半成品(只能通过命令行调用,无法使用php代码生成)html2image(http://www.guangmingsoft.net/htmlsnapshot/html2image.htm),没办法,习惯直接在代码中统一使用纯语言代码实现,所以继续google,然后找到了一个方案:html》pdf》image(来源:http://buffernow.com/),不得不说此方案是在对php非常熟悉的情况下才能想得到。
  原本打算直接使用他的开源方案,但在应用过程中发现有问题:无中文字体,添加中文字体后网页中整段的中文在图片中只显示一行,其他内容无法显示。
  这是要逼着我去研究他的开源代码的节凑啊,不过好在这个开源项目的意义是证实了html》pdf》image方案是可行的。
  把他的代码拆开来看,发现问题出在html网页生成pdf阶段,由于作者改写了tcpdf方案形成了html2pdf开源包,但是改写得并不好,对中文支持不够,于是抛弃了该作者的开源框架,直接采用稳定的tcpdf以及imagick转换html至pdf再转至image。
  这个过程略显艰辛啊(php没有正式学习过,一般都是拿起项目就开工,用到什么查什么的),从中午一直持续到晚上2点,整整14个小时啊,我的神,我认为有必要进行总结下,避免下次碰到同样的场景又忘掉了。
  现在开始吧:
  1.项目采用的成熟的开源方案:tcpdf(http://www.tcpdf.org/index.php)、imagick(php的一个库,类似gd库,需要在操作系统层面安装库文件,同时需要在php.ini中加入动态链接库)。
  2.首先需要将html生成pdf:这里要注意的是中文的处理,中文乱码在无数的地方出现过,需要确保的一点是所有的数据交换都采用utf8字符集,这里html采用fckeditor通过post提交的,首先是需要设置web服务器接收字符为utf8,其次new tcpdf时需要设置编码为中文,

$pdf = new TCPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false);
  3.tcpdf默认不包含中文字库(中国人要崛起啊,得做点大的世界通用项目,到时候不放日文字库、德国字库啥的,哈哈),可供使用的中文字库很多,网传用得最多的是Droid Sans Fallback字体,所以我采用的是可以Droid Sans Fallback字库,既可以直接下载该字体的tcpdf版本(三个文件),也可以下载ttf字体,然后用tcpdf的工具生成三个文件,方式见http://www.5eyi.com/php-to-generate-pdf-the-perfect-support-for-the-chinese-to-address-the-garbage-tcpdf/
  4.字体准备好了,编码正确了,准备开工了,但是官方只有案例,没有文档,并且案例中大部分都是多段html代码一点点的往tcpdf对象中写入,而我需要的是直接写入一段html,然后生成pdf文档,所以需要参照案例精简下代码
  5.html生成pdf时设置字体时需要注意,字体设置不当会影响到后边pdf生成图片的过程,在本次改造项目中就因此困扰了4个小时,Droid Sans是一个字体集,设置pdf字体时有两种方式,一种是只把字体描述信息写入pdf文档中,pdf阅读工具解析的时候会从工具自身字体库或者系统引入对应的字体以显示文档,因此pdf文档会比较小,此时设置字体为‘stsongstdlight’;另外一种设置字体时把字体文件同时保存到pdf文档中,即使pdf阅读工具或者系统中没有该字体时仍然能够解析并显示文档,因此文档会比较大,此时设置字体为‘droidsansfallback’;因为刚开始字体设置‘stsongstdlight’,导致后边使用imagick从pdf生成图片时始终无法生成;接着各种控制变量法,一步一步的找原因,最终定位到字体位置,字体‘stsongstdlight’导致无法生成图片,经完成的google指引,发现了Droid Sans字体有两种设置方式,再尝试两种设置字体的设置方式发现当字体设置为‘droidsansfallback’时生成的pdf文档才能生成图片【这里我感觉是服务器上缺少Droid Sans字体库,如果把Droid Sans字体库安装到服务器上是否也能生成图片呢?由于项目结束已经很晚了,所以没有去调研】
  6.写入tcpdf对象的html代码必须是无错误的并且符合html规范的代码,否则tcpdf会报错,通常由fckeditor生成的html代码都会对双引号转义,会导致"变成了\",这个转义不能被tcpdf识别,所以需要去掉转义字符\
  7.图片版权:生成的图片上需要加上产品的水印,既可以在pdf生成图片环节添加,也可以在html生成pdf阶段添加,个人认为pdf创建阶段添加会更简单,此项目中由于时间关系,我只是在html结尾部分简单的增加了一个网站标识(因为pdf是按照html格式生成的,所以可以修改html格式使得生成的pdf更美观、水印切合度更高)。
  好了,至此html生成pdf文档成功了,代码如下:

$pdf = new TCPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false);
$pdf->SetCreator(PDF_CREATOR);
$pdf->SetMargins(PDF_MARGIN_LEFT, PDF_MARGIN_TOP, PDF_MARGIN_RIGHT);
$pdf->SetAutoPageBreak(TRUE, PDF_MARGIN_BOTTOM);
$pdf->setImageScale(PDF_IMAGE_SCALE_RATIO);
$pdf->AddPage();
$pdf->SetFont('droidsansfallback', '', 16);
$testhtml=str_replace("\\","",$html).'<br/><div align="right">地歌网:www.diggg.com.cn</div>';
$pdf->writeHTML($testhtml, true, 0, true, true);
$pdf->lastPage();
$pdf->Output($config['webroot'].'/temp/temp'.$id.'.pdf','f');
   接下来我们就开始采用imagick将pdf生成image
  8.首先得准备imagick系统环境,得安装imagick系统安装包(window见http://www.gretheer.com/2013/09/installing-imagemagick-on-windows-and-using-with-php-imagick.html,linux直接使用yum安装),安装成功后打开命令行输入convert 查看是否正常执行;其次得安装php动态链接库,这是最麻烦的阶段,动态链接库必须和操作系统版本、php版本一致,否则无法使用,悲剧的是楼主用的php是wampp3.2.1中的带的php,版本是5.4.16,操作系统是window7 64位,找遍了google都没能找到能正常安装的imagick动态库,花了2小时后,我放弃了在window7上本地调试工作,直接在centos6的服务器上安装imagick,结果centos上imagick动态库成功集成到php中。在此吐槽下:这个php的动态库真是麻烦,兼容性太差了
  9.imagick的官方教程地址(http://www.php.net/manual/zh/book.imagick.php),其实imagick的功能非常强大,但是相关的功能介绍文档资料太少了,时间关系无法一个方法一个方法的尝试,只能google得到我需要的东东,一开始用最简单的代码实现功能如

$img = new imagick($pdf_file);
$img->setImageFormat('jpg');
$img->writeImage($save_to);
  可以正常生成图片,但是图片中只包含pdf的最后一页的内容;如果pdf是单页的可以这样操作,但是如果pdf是多页的,这种方式就不适用了,因为没有相关文档,一开始想既然可以把pdf最后一页的内容生成图片,那么一定可以把所有页面都生成图片,然后再利用图片库把图片拼接起来

代码思路 写道

1.获取pdf的页数 [$Image = new Imagick($pdfpath.'.pdf'); $num_page = $Image->getnumberimages();]
2.把每一页都生成图片[ $Image = new Imagick($pdfpath.'.pdf')]
3.获取每一页图片的高度并相加得到后续拼合图片时需要用到的画布的高度
4.新建一个画布
5.依次把图片写入画布,注意图片在画布中的起始坐标,横坐标是0,纵坐标是前边几张图片的高度之和
6.关闭画布,并输出图片文件
  写好代码后发现居然有直接把多页pdf直接生成图片的方法,悲剧啊,花了那么长时间,居然有更简单的方法,好吧当然采用简单的思路啦

$pdfpath=$config['webroot'].'/temp/temp'.$id.'.pdf';
$im = new Imagick();
$im->readImage($pdfpath);
$im -> resetIterator();
$imgs = $im->appendImages(true);
$imgs->setImageFormat( "jpg" );
$img_name = $id.'.jpg';
$imgs->writeImage( $config['webroot']."/temp/".$img_name);
$imgs->clear();
$imgs->destroy();
$im->clear();
$im->destroy();

  好了,到此html生成图片全过程完成
  完整的代码:

//缓存正文的图片
include_once($config['webroot']."/tcpdf/tcpdf.php");
$pdf = new TCPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false);
$pdf->SetCreator(PDF_CREATOR);
$pdf->SetMargins(PDF_MARGIN_LEFT, PDF_MARGIN_TOP, PDF_MARGIN_RIGHT);
$pdf->SetAutoPageBreak(TRUE, PDF_MARGIN_BOTTOM);
$pdf->setImageScale(PDF_IMAGE_SCALE_RATIO);
$pdf->AddPage();
$pdf->SetFont('droidsansfallback', '', 16);
$testhtml=str_replace("\\","",$con).'<br/><div align="right">地歌网:www.diggg.com.cn</div>';
$pdf->writeHTML($testhtml, true, 0, true, true);
$pdf->lastPage();
$pdf->Output($config['webroot'].'/temp/temp'.$id.'.pdf','f');
$pdfpath=$config['webroot'].'/temp/temp'.$id.'.pdf';
$im = new Imagick();
$im->readImage($pdfpath);
$im -> resetIterator();
$imgs = $im->appendImages(true);
$imgs->setImageFormat( "jpg" );
$img_name = $id.'.jpg';
$imgs->writeImage( $config['webroot']."/temp/".$img_name);
$imgs->clear();
$imgs->destroy();
$im->clear();
$im->destroy();
unlink($pdfpath);
//缓存结束

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-364152-1-1.html 上篇帖子: Discuz!源代码分析系列(4)-./include/template.func.php(模板) 下篇帖子: Cent OS 5.5 安裝 PHP 5.3 + PHPUnit 3.4 (教學備忘筆記)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表