意见箱
恒创运营部门将仔细参阅您的意见和建议,必要时将通过预留邮箱与您保持联络。感谢您的支持!
意见/建议
提交建议

PHP windoews调用OpenOffice实现word/ppt转PDF-附带demo

来源:恒创科技 编辑:恒创科技编辑部
2024-02-02 20:45:59


包有用

最近做一个项目,需要将用户上传的word,ppt文档转成PDF文档保存并打印,在网上找了很多资料,并不全面,爬过的坑记录下来。


PHP windoews调用OpenOffice实现word/ppt转PDF-附带demo

excel输出pdf还没成功

下面是操作步骤:

1、安装免费的openOffice软件,请至openoffice.org下载最新版本。

2、JDK支持,请自行搜索下载最新版本JDK。

3、安装完openOffice后,在开始--运行中输入Dcomcnfg打开组件服务。在组件服务—计算机—我的电脑—DCOMP配置中,选择

PHP windoews调用OpenOffice实现word/ppt转PDF-附带demo_php

在这两项上分别点击右键属性,打开属性面板如下图:

PHP windoews调用OpenOffice实现word/ppt转PDF-附带demo_html_02

PHP windoews调用OpenOffice实现word/ppt转PDF-附带demo_desktop_03

PHP windoews调用OpenOffice实现word/ppt转PDF-附带demo_php_04

PHP windoews调用OpenOffice实现word/ppt转PDF-附带demo_html_05

选择安全选项卡,分别在启动和激活权限和访问权限两项上点自定义,添加Everyone的权限。

选择标识选项卡,选择交互式用户。

4、安装完openOffice后,请先打开一次确认可以正常运行软件,然后退出后用命令行运行以下命令。

先到安装目录下,例如:C:\Program Files\OpenOffice 4\program\

这里很多人不知道怎么进,截图说下,直接输入cmd

PHP windoews调用OpenOffice实现word/ppt转PDF-附带demo_html_06

执行命令:

soffice -headless-accept="socket,host=127.0.0.1,port=8100;urp;" -nofirststartwizard

成功后即在后台运行了该软件。

5、如果是php5.4.5以前版本,需要在php.ini里把com.allow_dcom = true打开,即去掉前面的分号。如果是以后版本,需要在php.ini 里增加一行扩展extension=php_com_dotnet.dll,然后检查php的ext目录中是否存在该dll文件,如果没有请自行下载对应版本的dll。然后重启apache或IIS服务器。

到了这里就是调错阶段了,很多时候就是路径问题

( ! )Fatal error: Uncaught exception 'com_exception' with message '<b>Source:</b> [automation bridge] <br/><b>Description:</b> com.sun.star.task.ErrorCodeIOException: ' in I:\phpStudy\WWW\DocPreview\test2.php on line27

( ! )com_exception: <b>Source:</b> [automation bridge] <br/><b>Description:</b> com.sun.star.task.ErrorCodeIOException: in I:\phpStudy\WWW\DocPreview\test2.php on line27

.注意:​​$input_url​​​和​​$output_url​​的路径需要写绝对路径

给个路径示例:

dirname(__FILE__)."/file/33.pptx"

很重要,请多试试

再说说yii2中的处理

类:

<?php
namespace app\services;
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2018/8/23
* Time: 14:43
*/

/**
* office文档转换为PDF类
* @author jinzhonghao <954299193@qq.com> created 2015-04-23
*/


class Office2Pdf
{
private $osm;

public function __construct()
{
$this->osm = new \COM("com.sun.star.ServiceManager")or die ("Please be sure that OpenOffice.org is installed.n");
}

public function MakePropertyValue($name,$value)
{
$oStruct = $this->osm->Bridge_GetStruct("com.sun.star.beans.PropertyValue");
$oStruct->Name = $name;
$oStruct->Value = $value;
return $oStruct;
}

public function transform($input_url, $output_url)
{
$args = array($this->MakePropertyValue("Hidden",true));

$oDesktop = $this->osm->createInstance("com.sun.star.frame.Desktop");
//var_dump($input_url);die();
$oWriterDoc = $oDesktop->loadComponentFromURL($input_url,"_blank", 0, $args);

$export_args = array($this->MakePropertyValue("FilterName","writer_pdf_Export"));
//var_dump($output_url,$export_args);die();
$oWriterDoc->storeToURL($output_url,$export_args);
$oWriterDoc->close(true);
return $this->getPdfPages($output_url);
}

public function runs($input,$output)
{
$input = "file:///" . str_replace("\\","/",$input);
$output = "file:///" . str_replace("\\","/",$output);
return $this->transform($input, $output);
}

/**
* 获取PDF文件页数的函数获取
* 文件应当对当前用户可读(linux下)
* @param [string] $path [文件路径]
* @return int
*/
public function getPdfPages($path)
{
if(!file_exists($path)) return 0;
if(!is_readable($path)) return 0;
// 打开文件
$fp=@fopen($path,"r");
if (!$fp)
{
return 0;
}
else
{
$max=0;
while(!feof($fp))
{
$line = fgets($fp,255);
if (preg_match('/\/Count [0-9]+/', $line, $matches))
{
preg_match('/[0-9]+/',$matches[0], $matches2);
if ($max<$matches2[0]) $max=$matches2[0];
}
}
fclose($fp);
// 返回页数

return $max;
}
}

}

调用:

  /**
* 预览
* create dahai
* time 2018/08/09
* */
public function actionPreview()
{
$id = intval(\Yii::$app->request->get('id'));
$content = \app\models\Content::findOne($id);
$html = '暂不支持预览';
if (!$content)
{
$html = '资源不存在';
return $this->renderPartial('preview', ["html"=>$html]);
}
//获取名字
$new_name = substr($content['name'],0,strrpos($content['name'],'.'));
$hostInfo = \Yii::$app->request->hostInfo;
//获取尾缀
$wei_name=explode(".", $content['name']);
$last=$wei_name[count($wei_name)-1];
//excel文件暂时不支持预览
if($last=="xls" || $last=="xlsx"){
return $this->returnData("", -1, '暂时不支持预览'.$last."文件");
}
//拼装名字
$source = ROOT_DIR.$content->url;
$pdf_url =ROOT_DIR."/upload/pdf/".$new_name."_".$last.".pdf";
$last_url = $hostInfo."/upload/pdf/".$new_name."_".$last.".pdf";
$source = iconv("UTF-8", "gbk",$source);
$pdf_url = iconv("UTF-8", "gbk",$pdf_url);
// var_dump($source,$pdf_url);die();
$office2pdf = new \app\services\Office2Pdf();
$result = $office2pdf->runs($source,$pdf_url);
if($result > 0){
// $url = \Yii::$app->params['source.domain'] . $content->url;//原路径
$data = [
'type' =>$content->type,
'url' =>$last_url,
];
return $this->returnData($data,1,'预览成功');
}else{
return $this->returnData("", -1, "预览文件失败");
}
}

网上很多介绍是由于jdk中的没有字体导致乱码,而我遇到的是转换过程并未报错,但转换后的PDF中是乱码,尝试在jre/lib/fonts/中增加字体,还是不能解决问题,因此可以判断非jre字体问题,是linux系统字体问题。

用vim /etc/fonts/fonts.conf,可以看到系统字体文件在/usr/share/fonts,将windows系统字体文件连接到此目录下

ln -s /usr/local/fonts fonts

然后更新缓存:fc-cache

重启openoffice:

/opt/openoffice4/program/soffice -headless -accept="socket,host=127.0.0.1,port=8100;urp;" -nofirststartwizard &

再转换,字体终于显示正确,不再有乱码

上一篇: php查找某个值是否存在于多维数组中 下一篇: 手机怎么远程登录云服务器?