文件预览的效果图(附带导出pdf文件和打印功能):
实现方式如下:
1.打开模板word文件 , 在对应地方打上书签;
2.在php.ini中加上 extension=php_com_dotnet.dll ; 目前只支持windows系统
3.代码如下
用数组来记录书签和表字段的对应关系 如果经常变动也可以用数据库来记录
'PROJECT_MAP' => [
//用数组来记录书签和表字段的对应关系 如果经常变动也可以用数据库来记录
'id' => 'id',
'project_name' => 'name',
'project_type' => 'ptype_name',
'user_department' => 'user_department',
'project_code' => 'project_code',
'lianxiren' => 're_man',
'lianxi_telephone' => 're_phone',
],
public function preview()
{
$pid = I('pid');
$type = I('type');
$map = $this->getMap($pid, $type);
//getmap方法就是获取上方project_map形式的一个数组
$tempPath = '/upload/project/template/'.$type.'.doc';
//模板文件的路径及文件名(我的文件名是英文,中文转码)
$word = new \Lib\Word(); //注意命名空间
list($ret, $mix) = $word->createDocUseComFromTemp($map, $tempPath, $filename);
if (!$ret) {
exit($mix);
}
$this->preview($mix,$pid);
//因为预览文件大概需要5-6秒的时间,这里加入缓存机制 , 如果不带id 会根据模板文件名来生成缓存文件 ,
//就会导致不同项目预览同一个模板时 会调用同一个缓存文件, 所以把pid拼接到文件名中,即不同项目id生成不同的缓存文件
}
public function getMap($pid, $type)//获取书签对应映射的值
{
$project = M('yy_project')->where("id=$pid")->find();
//处理数据
$project['procect_sn'] = end(explode('-', $project['code']));
$map = C('PROJECT_MAP');
foreach ($map as $k => &$v) {
$v = $project[$v];
}
//对数据的处理在这里进行
//图片传入路径就行 可以实现签名功能
return array_filter($map);
}
public function preview($word_path = '' ,$pid = null)
{
if (!$word_path) echo CLNG('param_error');
$fileExt = explode('.', $word_path)[1] ?: 'doc';
if (!$fileExt) echo '需要预览的word不是合法的.doc或者.docx';
$word_path = get_absolute_path($word_path, true);//获取文件的绝对路径 方法自己封装
//这里会检测是否是合法路径
try {
$Word = new \Lib\Word();
$Word->dcomPreview($word_path,true,$pid);//使用DCOM组件,服务器需要安装word
} catch (\Think\Exception $e) {
echo '预览失败:'.$e->getMessage();
}
}
public function download($word_path = '', $file_name = '', $ext = '')
{
// $word_path = $word_path ?: 'D:/test.doc';//for debug;
$word_path || $this->ccerror(CLNG('param_error'));
$Word = new \Lib\Word();
$Word->download($word_path, $file_name, $ext);
}
word.class.php:
<?php
/**
* 封装word的一些操作,有的使用PHPWord,有的时候使用openoffice,有时候使用COM ms-word服务组件
* Author Dicl & Sean http://www.yycmedia.cn.
*
* DCOM word.application API
* ActiveDocument->SaveAs() 只能保存doc 或者docx文件
* ActiveDocument->ExportAsFixedFormat() 导出pdf文件,第一个参数传入pdf文件完成文件名即可,.html等其他格式的文件不知是否也是如此导出TOTST
*/
namespace Lib;
use Lib\OpenOffice2Pdf as OO2Pdf;
class Word
{
const MS_WORD_COM_SERVICE_NAME = 'word.application';
const MS_WORD_DCOM_NAME = 'Microsoft Word 97-2003 Document'; //ms_word的DCOM组件的名称
const PDF_HEADER = 'Content-type:application/pdf';
/**
* 使用phpword预览word的实现 主要针对Word2007(.docx)以上有效
* 思路:加载.docx phpword转换成 .html 输出html给浏览器 浏览器加载html实现预览 可能部分样式会有出入.
*
* @param string $inputFileName word文件路径
* @param string $inputFileType word文件的类型(Word2007,MsDoc,参见PHPWord源码)
*
* @return string HTML content-type=application/html
*/
public function phpWordPreview($inputFileName = '', $inputFileType = '')
{
// $inputFileName = $inputFileName ?: 'D:/test.docx'; //for debug.
vendor('autoload', '', '.php'); //引入自动加载类,用于加载第三方类库
if (!$inputFileType) {
$file_ext = explode('.', $inputFileName)[1];
if ('docx' == $file_ext) {
$inputFileType = 'Word2007'; //Word2007及以上
} else {
// $this->openOfficePreview($inputFileName);//调用openoffice处理吧
$inputFileType = 'MsDoc'; //Word97-2003 但是会乱码 何解? TODO
}
}
$objReader = \PhpOffice\PhpWord\IOFactory::createReader($inputFileType);
$objPHPFile = $objReader->load($inputFileName);
$objWriter = \PhpOffice\PhpWord\IOFactory::createWriter($objPHPFile, 'HTML');
// $objWriter->save('D:/11.doc');//可用Word2007 writer 写出word2003文档 NOTE
$objWriter->save('php://output'); //直接输出html内容,前端用iframe承载
}
/**
* 使用windows服务器上的DCOM组件,将文档打开另存为pdf,然后再读取该文件pdf输出给浏览器.
* NOTE:支持.doc和.docx,但是依赖windows服