打开COM扩展
打开php.ini文件,在文件最后添加:
extension=com_dotnet
查看php.ini中的disable_classes确保com类没有被禁用:
disable_classes =
重启php,查看phpinfo,看到以下信息则说明开启成功:
安装office2010
安装过程省略。
配置office组件服务
按 win+R 快捷键进入运行菜单,输入 Dcomcnfg
找到: [组件服务] —— [计算机]—— [我的电脑] —— [DCOM配置] —— [Microsoft Word 97-2003文档],右键设置属性,设置“标识”为:下列用户,点击“浏览”选择你当前登录的账户并输入密码,如下图:
注:如果找不到Microsoft Word程序,这主要是64位系统的问题,word是32位的组件,所以在正常的系统组件服务里是看不到的。可以通过在运行里面输入comexp.msc -32
来打开32位的组件服务,在里就能看到word组件了。
设置权限
将上一步的账户添加到自定义里面,并开启所有权限:
添加受信任位置
打开某些受保护的word文档时,word会提示:检测到此文件存在一个问题。为帮助保护您的计算机,不能打开此文件。
遇到该问题时,可以通过设置“受信任位置”来解决。
点击左上角的“文件”->“选项”:
点击“信任中心”->“信任中心设置”:
在“受信任位置”中点击“添加新位置”,将文件上传位置添加进去即可:
PHP代码
PHP代码如下:
$wordInPath = __DIR__ ."/2.docx"; //要转换的word文档的路径
$pdfOutPath = __DIR__ ."/2.pdf"; //要输出的pdf的路径
word2pdf($wordInPath,$pdfOutPath);
function word2pdf($wordPath,$pdfPath)
{
//生成临时文件
$tmpfile = tempnam( sys_get_temp_dir(), "TMP" );
copy($wordPath,$tmpfile);
$word = new COM("Word.Application") or die ("Could not initialise Object.");
// set it to 1 to see the MS Word window (the actual opening of the document)
$word->Visible = 0;
// recommend to set to 0, disables alerts like "Do you want MS Word to be the default .. etc"
$word->DisplayAlerts = 0;
// open the word 2007-2013 document
$word->Documents->Open($tmpfile);
// save it as word 2003
// convert word 2007-2013 to PDF
//判断要生成的文件名是否存在
if(file_exists($pdfPath)) {
//存在就删除
unlink ($pdfPath);
}
$word->ActiveDocument->ExportAsFixedFormat($pdfPath, 17, false, 0, 0, 0, 0, 7, true, true, 2, true, true, false);
// quit the Word process
$word->ActiveDocument->Close(0);
$word->Quit(false);
// clean up
unset($word);
}
封装好的类:
class Dcs
{
private $downloadUrl;
private $outputPath;
private $error;
public function setDownloadUrl($url)
{
$this->downloadUrl = $url;
}
public function setOutputPath($path)
{
$this->outputPath = $path;
if(!is_dir($path)) @mkdir($path,0777,true);
}
public function getError()
{
return $this->error;
}
function convert()
{
$result = $this->remoteFileExists($this->downloadUrl);
if ($result === false) {
$this->error = '下载文件失败';
return false;
}
$content = $this->curlGet($this->downloadUrl);
if($content===false) return false;
$tmpfile = tempnam( $this->outputPath, "TMP" );
file_put_contents($tmpfile,$content);
$pdfName = time() . mt_rand(1000, 9999) . '.pdf';
$pdfPath = $this->outputPath . '/'.$pdfName;
$this->word2pdf($tmpfile,$pdfPath);
return $pdfPath;
}
private function word2pdf($wordPath,$pdfPath)
{
$word = new \COM("Word.Application") or die ("Could not initialise Object.");
$word->Visible = 0;
$word->DisplayAlerts = 0;
$word->Documents->Open($wordPath);
if(file_exists($pdfPath)) {
unlink ($pdfPath);
}
$word->ActiveDocument->ExportAsFixedFormat($pdfPath, 17, false, 0, 0, 0, 0, 7, true, true, 2, true, true, false);
$word->ActiveDocument->Close(0);
$word->Quit(false);
unset($word);
}
private function getWordContent($wordPath)
{
$word = new \COM("Word.Application") or die ("Could not initialise Object.");
$word->Visible = 0;
$word->DisplayAlerts = 0;
$word->Documents->Open($wordPath);
$text= $word->ActiveDocument->content->Text;
$word->ActiveDocument->Close(0);
$word->Quit(false);
unset($word);
$text = iconv('gbk','utf-8',$text);
return $text;
}
private function curlGet($url = '', $options = array())
{
// return file_get_contents($url);
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);//返回response头部信息
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
if (!empty($options)) {
curl_setopt_array($ch, $options);
}
//https请求 不验证证书和host
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
$data = curl_exec($ch);
if($data === false)
{
$this->error = 'Curl error: ' . curl_error($ch);
return false;
}
curl_close($ch);
return $data;
}
private function remoteFileExists($url){
return (bool)preg_match('~HTTP/1\.\d\s+200\s+OK~', @current(get_headers($url)));
}
}
//使用类
define('WEBROOT', realpath(__DIR__));
$downloadUrl = $_POST['downloadUrl'];
$data['result'] = 1;
if(empty($downloadUrl)) {
$data['message'] = '缺少参数:downloadUrl';
echo json_encode($data, JSON_UNESCAPED_UNICODE + JSON_UNESCAPED_SLASHES);exit();
}
$dcs = new Dcs();
$dcs->setOutputPath(WEBROOT.'/output/'.date('Y').'/'.date('m'));
$dcs->setDownloadUrl($downloadUrl);
$result = $dcs->convert();
if($result===false){
$data['message'] = $dcs->getError();
echo json_encode($data, JSON_UNESCAPED_UNICODE + JSON_UNESCAPED_SLASHES);exit();
}
$result = str_replace(WEBROOT,'',$result);
$result = str_replace("\\",'/',$result);
$data['result'] = 0;
$data['data'][] = 'http://xxx/dcs/onlinefile/'.$result;
$data['message'] = '转换成功';
$data['type'] = 3;
echo json_encode($data, JSON_UNESCAPED_UNICODE + JSON_UNESCAPED_SLASHES);exit();
更多office的api
https://docs.microsoft.com/zh-cn/office/vba/api/word.document.exportasfixedformat
使用WPS
有的文件用word打不开,用wps却可以,同时wps具有免费的优点,也可以考虑使用wps来实现。
安装wps
有的wps版本(例如个人版)不包含com组件,我安装的是专业版:
https://www.ghxi.com/wps2019zfb.html
配置wps组件服务
配置方法跟office一样,这里不再赘述。
PHP代码
调用方式跟office也一模一样,只是new COM时传入的名称不同:
new COM("KWPS.Application")
注意:wps 8.0前的接口名称为:WPS.Application
9.0之后的版本接口名称:
控件名 | name |
---|---|
WPS文字 | KWPS.Aplication |
WPS的Excel | KET.Application |
WPS的演示文档 | KWPP.Application |