文库系统是如何在windows环境中将office文件转换成pdf或图片的?

最近在做一个文库网站项目,需要让文档能在网页中预览。 在网页上能预览,需要实现word文件转pdf, ppt文件转图片。

我实现的逻辑是借用windows office 软件,通过调用PHP执行office转换命令。以下是我的操作步骤,仅供大家参考。

一、 服务器环境安装和设置

  1. 购买windows 服务器,安装chrome, rar;服务器系统设置(电源>高级计划>从不关闭显示器)
  2. 安装宝塔,配置LNMP环境
  3. 安装office2013
  4. 打开php.ini,搜索php_com_dotnet和php_com_dotnet: extension=php_com_dotnet.dll //把前面的分号去掉 com.allow_dcom = true //改为true
  5. 打开php的安装目录下的 php.in 文件,找到 disable_classes = 这行。果然,com 在 disable_classes = 里面,代码如下: disable_classes = com 把 com 删除,这行代码变为: disable_classes =
  6. 重启php
  7. win+r 输入 dcomcnfg 进入配置office组件服务权限配置
  8. 如果这种方式找不到组件可以使用另一种方式,输入mmc -32, 添加或删除管理单元

添加后,再次进入dcomcnfg,组件配置

记住 标识为 交互式用户

二、 添加接口网站

三、 接口代码分享

<?php

set_time_limit(0);

$keys = 'HQRux0Z6RF00a1xj','K86njv0Vbxgg390p','8GA3KGsAtRed7w5L','bGcsJ67xdLEsTxxL';

$appkey = $_POST'appkey';

$file = $_POST'file';

$action = $_POST'action';

$rootPath = rtrim($_SERVER'DOCUMENT_ROOT',DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR;

$current_url = get_url();

$rootUrl = rtrim(str_replace(basename($current_url),'',$current_url),'/')."/";

if(empty($appkey)||empty($file)||empty($action))

{

代码语言:txt
复制
$result =  [
代码语言:txt
复制
        'error' => 1,
代码语言:txt
复制
        'msg' => '参数错误',
代码语言:txt
复制
        'code'=>500,
代码语言:txt
复制
        'data'=>[]
代码语言:txt
复制
    ];
代码语言:txt
复制
echo_json($result);

}

else

{

代码语言:txt
复制
if(!in_array($appkey,$keys))
代码语言:txt
复制
{
代码语言:txt
复制
     $result =  [
代码语言:txt
复制
        'error' => 1,
代码语言:txt
复制
        'msg' => '非法appkey',
代码语言:txt
复制
        'code'=>500,
代码语言:txt
复制
        'data'=>[]
代码语言:txt
复制
    ];
代码语言:txt
复制
    echo_json($result);
代码语言:txt
复制
}
代码语言:txt
复制
else
代码语言:txt
复制
{
代码语言:txt
复制
     //个人目录空间
代码语言:txt
复制
     $ownerPath = str_replace('/',DIRECTORY_SEPARATOR,$rootPath).$appkey.DIRECTORY_SEPARATOR;
代码语言:txt
复制
     $ownerUrl = $rootUrl.$appkey."/";
代码语言:txt
复制
     if(is_dir($ownerPath))
代码语言:txt
复制
     {
代码语言:txt
复制
         $dirsize = CalcDirectorySize($ownerPath);
代码语言:txt
复制
         if($dirsize>=524288000)//超过500Mb,清空目录
代码语言:txt
复制
         {
代码语言:txt
复制
              dir_delete($ownerPath);
代码语言:txt
复制
              dir_create($ownerPath);
代码语言:txt
复制
         }
代码语言:txt
复制
     }
代码语言:txt
复制
     else
代码语言:txt
复制
     {
代码语言:txt
复制
         dir_create($ownerPath);
代码语言:txt
复制
     }
代码语言:txt
复制
     chmod($ownerPath,0777);
代码语言:txt
复制
     $filename = basename($file);
代码语言:txt
复制
     $filemd5 =  md5($filename);
代码语言:txt
复制
     $sourceFile = $ownerPath.$filemd5.'.'.fileext($filename);
代码语言:txt
复制
     $workpath =  $ownerPath.$filemd5.DIRECTORY_SEPARATOR;
代码语言:txt
复制
     $workUrl = $ownerUrl.$filemd5."/";
代码语言:txt
复制
     if(!is_dir($workpath))dir_create($workpath);
代码语言:txt
复制
     chmod($workpath,0777);
代码语言:txt
复制
     if(!file_exists($sourceFile))file_put_contents($sourceFile,https_request($file));
代码语言:txt
复制
     chmod($sourceFile,0777);
代码语言:txt
复制
     //转换成pdf
代码语言:txt
复制
     if($action=='topdf')
代码语言:txt
复制
     {
代码语言:txt
复制
         if(!file_exists($sourceFile))
代码语言:txt
复制
         {
代码语言:txt
复制
             $result =  [
代码语言:txt
复制
                'error' => 1,
代码语言:txt
复制
                'msg' => '转码失败',
代码语言:txt
复制
                'code'=>200,
代码语言:txt
复制
                'data'=>[]
代码语言:txt
复制
            ];
代码语言:txt
复制
             echo_json($result);
代码语言:txt
复制
         }
代码语言:txt
复制
         $ext = fileext($sourceFile);
代码语言:txt
复制
         $pdfname = str_replace('.'.$ext,'.pdf',basename($sourceFile));
代码语言:txt
复制
         $pdfPath = $workpath.$pdfname;
代码语言:txt
复制
         $pdfUrl =  $workUrl.$pdfname;
代码语言:txt
复制
         if(in_array($ext,array('doc','docx','wps')))
代码语言:txt
复制
         {
代码语言:txt
复制
              $word = new COM("word.Application") or die("Could not initialise Object");
代码语言:txt
复制
              $word->Documents->Open($sourceFile);
代码语言:txt
复制
              $word->ActiveDocument->ExportAsFixedFormat($pdfPath, 17, false, 0, 0, 0, 0, 7, true, true, 2, true, true, false);
代码语言:txt
复制
              $word->Quit(false);
代码语言:txt
复制
              unset($word);
代码语言:txt
复制
         }
代码语言:txt
复制
         if(in_array($ext,array('ppt','pptx','dps')))
代码语言:txt
复制
         {
代码语言:txt
复制
              $ppt = new COM("powerpoint.application") or die("Unable to instantiate Powerpoint");
代码语言:txt
复制
              $presentation = $ppt->Presentations->Open($sourceFile, false, false, false);
代码语言:txt
复制
              $presentation->SaveAs($pdfPath,32,1);
代码语言:txt
复制
              $presentation->Close();
代码语言:txt
复制
              $ppt->Quit();
代码语言:txt
复制
              unset($ppt);
代码语言:txt
复制
         }
代码语言:txt
复制
         if(in_array($ext,array('xls','xlsx','et')))
代码语言:txt
复制
         {
代码语言:txt
复制
               $excel = new COM("excel.application") or die("Unable to instantiate excel");
代码语言:txt
复制
               $workbook = $excel->Workbooks->Open($sourceFile, null, false, null, "1", "1", true);
代码语言:txt
复制
               $workbook->ExportAsFixedFormat(0, $pdfPath);
代码语言:txt
复制
               $workbook->Close();
代码语言:txt
复制
               $excel->Quit();
代码语言:txt
复制
               unset($excel);
代码语言:txt
复制
         }
代码语言:txt
复制
         $result =  [
代码语言:txt
复制
            'error' => 0,
代码语言:txt
复制
            'msg' => '转码成功',
代码语言:txt
复制
            'code'=>200,
代码语言:txt
复制
            'data'=>['pdf'=>$pdfUrl]
代码语言:txt
复制
        ];
代码语言:txt
复制
        echo_json($result);
代码语言:txt
复制
     }
代码语言:txt
复制
     //PPT转图片
代码语言:txt
复制
     if($action=='ppt2img')
代码语言:txt
复制
     {
代码语言:txt
复制
         $powerpnt = new COM("powerpoint.application") or die("Unable to instantiate Powerpoint");
代码语言:txt
复制
         $presentation = $powerpnt->Presentations->Open2007($sourceFile, false, false, false,true) or die("Unable to open presentation");
代码语言:txt
复制
         //$presentation = $powerpnt->Presentations->Open($sourceFile, false, false, false) or die("Unable to open presentation");
代码语言:txt
复制
         foreach($presentation->Slides as $slide)
代码语言:txt
复制
         {
代码语言:txt
复制
            $slideName = $slide->SlideNumber-1;
代码语言:txt
复制
            $to =  $workpath.$slideName.".jpg";
代码语言:txt
复制
            $slide->Export($to, "jpg", "960", "540");
代码语言:txt
复制
            $urls[] = $workUrl.$slideName.".jpg";
代码语言:txt
复制
         }
代码语言:txt
复制
         $presentation->Close();
代码语言:txt
复制
         $powerpnt->Quit();
代码语言:txt
复制
         $powerpnt = null;
代码语言:txt
复制
         $result =  [
代码语言:txt
复制
            'error' => 0,
代码语言:txt
复制
            'msg' => '转码成功',
代码语言:txt
复制
            'code'=>200,
代码语言:txt
复制
            'data'=>['imgs'=>$urls]
代码语言:txt
复制
         ];
代码语言:txt
复制
         echo_json($result);
代码语言:txt
复制
     }
代码语言:txt
复制
}

}

/****以下是全局函数****/

function echo_json($arr){

代码语言:txt
复制
ob_clean();
代码语言:txt
复制
header('Content-type: application/json');
代码语言:txt
复制
echo json_encode($arr);exit;

}

//Curl

function https_request($url,$options = null,$data = null,$header = null){

代码语言:txt
复制
$curl = curl_init();
代码语言:txt
复制
curl_setopt($curl, CURLOPT_URL, $url);
代码语言:txt
复制
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
代码语言:txt
复制
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
代码语言:txt
复制
curl_setopt($curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); //强制协议为1.0
代码语言:txt
复制
curl_setopt($curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4 ); //强制使用IPV4协议解析域名
代码语言:txt
复制
if (!empty($data)){
代码语言:txt
复制
	curl_setopt($curl, CURLOPT_POST, 1);
代码语言:txt
复制
	curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($data));
代码语言:txt
复制
}
代码语言:txt
复制
(isset($options['header'])&&$options['header'])?curl_setopt($curl, CURLOPT_HEADER, 1): curl_setopt($curl, CURLOPT_HEADER, 0);//如果有响应头
代码语言:txt
复制
if(!empty($header))//如果有请求头
代码语言:txt
复制
{
代码语言:txt
复制
    $curl_header = array();
代码语言:txt
复制
    foreach($header as $key=>$value)
代码语言:txt
复制
    {
代码语言:txt
复制
        $curl_header[] = "$key:$value";
代码语言:txt
复制
    }
代码语言:txt
复制
    curl_setopt($curl,CURLOPT_HTTPHEADER, $curl_header);
代码语言:txt
复制
}
代码语言:txt
复制
if(isset($options['gzip'])&&$options['gzip']==1) curl_setopt($curl, CURLOPT_ENCODING, "gzip"); //如果页面开启了GZIP压缩
代码语言:txt
复制
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
代码语言:txt
复制
curl_setopt($curl, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:30.0) Gecko/20100101 Firefox/30.0');
代码语言:txt
复制
if(!empty($options['time_out']))
代码语言:txt
复制
{
代码语言:txt
复制
    curl_setopt($curl, CURLOPT_TIMEOUT, $options['time_out']);
代码语言:txt
复制
}
代码语言:txt
复制
else
代码语言:txt
复制
{
代码语言:txt
复制
    curl_setopt($curl, CURLOPT_TIMEOUT, 600);
代码语言:txt
复制
}
代码语言:txt
复制
curl_setopt ($curl, CURLOPT_REFERER, get_url());
代码语言:txt
复制
$output = curl_exec($curl);
代码语言:txt
复制
curl_close($curl);
代码语言:txt
复制
return $output;

}

function fileext($filename) {

代码语言:txt
复制
return strtolower(trim(substr(strrchr($filename, '.'), 1, 10)));

}

/*

  • 转化 \ 为 /
  • @param string $path 路径
  • @return string 路径
  • */ function dir_path($path) { $path = str_replace('\', '/', $path); if(substr($path, -1) != '/') $path = $path.'/'; return $path; } /**
  • 创建目录
  • @param string $path 路径
  • @param string $mode 属性
  • @return string 如果已经存在则返回true,否则为flase */ function dir_create($path, $mode = 0777) {
代码语言:txt
复制
if(is_dir($path)) return TRUE;
代码语言:txt
复制
$path = dir_path($path);
代码语言:txt
复制
$temp = explode('/', $path);
代码语言:txt
复制
$cur_dir = '';
代码语言:txt
复制
$max = count($temp) - 1;
代码语言:txt
复制
for($i=0; $i<$max; $i++) {
代码语言:txt
复制
	$cur_dir .= $temp[$i].'/';
代码语言:txt
复制
	if (@is_dir($cur_dir)) continue;
代码语言:txt
复制
	@mkdir($cur_dir, 0777,true);
代码语言:txt
复制
	@chmod($cur_dir, 0777);
代码语言:txt
复制
}
代码语言:txt
复制
return is_dir($path);

}

/*

  • 拷贝目录及下面所有文件
  • @param string $fromdir 原路径
  • @param string $todir 目标路径
  • @return string 如果目标路径不存在则返回false,否则为true / function dir_copy($fromdir, $todir) { $fromdir = dir_path($fromdir); $todir = dir_path($todir); if (!is_dir($fromdir)) return FALSE; if (!is_dir($todir)) dir_create($todir); $list = glob($fromdir.''); if (!empty($list)) { foreach($list as $v) { $path = $todir.basename($v); if(is_dir($v)) { dir_copy($v, $path); } else { copy($v, $path); @chmod($path, 0777); } } } return TRUE; } /**
  • 转换目录下面的所有文件编码格式
  • @param string $in_charset 原字符集
  • @param string $out_charset 目标字符集
  • @param string $dir 目录地址
  • @param string $fileexts 转换的文件格式
  • @return string 如果原字符集和目标字符集相同则返回false,否则为true */ function dir_iconv($in_charset, $out_charset, $dir, $fileexts = 'php|html|htm|shtml|shtm|js|txt|xml') { if($in_charset == $out_charset) return false; $list = dir_list($dir); foreach($list as $v) { if (pathinfo($v, PATHINFO_EXTENSION) == $fileexts && is_file($v)){ file_put_contents($v, iconv($in_charset, $out_charset, file_get_contents($v))); } } return true; } /**
  • 列出目录下所有文件
  • @param string $path 路径
  • @param string $exts 扩展名
  • @param array $list 增加的文件列表
  • @return array 所有满足条件的文件 / function dir_list($path, $exts = '', $list= array()) { $path = dir_path($path); $files = glob($path.''); foreach($files as $v) { if (!$exts || pathinfo($v, PATHINFO_EXTENSION) == $exts) { $list[] = $v; if (is_dir($v)) { $list = dir_list($v, $exts, $list); } } } return $list; } /**
  • 设置目录下面的所有文件的访问和修改时间
  • @param string $path 路径
  • @param int $mtime 修改时间
  • @param int $atime 访问时间
  • @return array 不是目录时返回false,否则返回 true / function dir_touch($path, $mtime = TIMESTAMP, $atime = TIMESTAMP) { if (!is_dir($path)) return false; $path = dir_path($path); if (!is_dir($path)) touch($path, $mtime, $atime); $files = glob($path.''); foreach($files as $v) { is_dir($v) ? dir_touch($v, $mtime, $atime) : touch($v, $mtime, $atime); } return true; } /**
  • 目录列表
  • @param string $dir 路径
  • @param int $parentid 父id
  • @param array $dirs 传入的目录
  • @return array 返回目录列表 / function dir_tree($dir, $parentid = 0, $dirs = array()) { global $id; if ($parentid == 0) $id = 0; $list = glob($dir.''); foreach($list as $v) { if (is_dir($v)) { $id++; $dirs$id = array('id'=>$id,'parentid'=>$parentid, 'name'=>basename($v), 'dir'=>$v.'/'); $dirs = dir_tree($v.'/', $id, $dirs); } } return $dirs; }

function dir_child($dir) {

代码语言:txt
复制
$dirArray[]=NULL;
代码语言:txt
复制
if (false != ($handle = opendir ( $dir ))) {
代码语言:txt
复制
    $i=0;
代码语言:txt
复制
    while ( false !== ($file = readdir ( $handle )) ) {
代码语言:txt
复制
        //去掉"“.”、“..”以及带“.xxx”后缀的文件
代码语言:txt
复制
        if ($file != "." && $file != "..") {
代码语言:txt
复制
            $dirArray[$i]=$file;
代码语言:txt
复制
            $i++;
代码语言:txt
复制
        }
代码语言:txt
复制
    }
代码语言:txt
复制
    //关闭句柄
代码语言:txt
复制
    closedir ( $handle );
代码语言:txt
复制
}
代码语言:txt
复制
return $dirArray;

}

/**

  • 删除目录及目录下面的所有文件
  • @param string $dir 路径
  • @return bool 如果成功则返回 TRUE,失败则返回 FALSE / function dir_delete($dir) { $dir = dir_path($dir); if (!is_dir($dir)) return FALSE; $list = glob($dir.''); foreach($list as $v) { is_dir($v) ? dir_delete($v) : @unlink($v); } return @rmdir($dir); }

function CalcDirectorySize($DirectoryPath) {

// I reccomend using a normalize_path function here

// to make sure $DirectoryPath contains an ending slash

// (-> http://www.jonasjohn.de/snippets/php/normalize-path.htm)

// To display a good looking size you can use a readable_filesize

// function.

// (-> http://www.jonasjohn.de/snippets/php/readable-filesize.htm)

$Size = 0;

$Dir = opendir($DirectoryPath);

if (!$Dir)

代码语言:txt
复制
return -1;

while (($File = readdir($Dir)) !== false) {

代码语言:txt
复制
// Skip file pointers
代码语言:txt
复制
if ($File[0] == '.') continue; 
代码语言:txt
复制
// Go recursive down, or add the file size
代码语言:txt
复制
if (is_dir($DirectoryPath . $File))      
代码语言:txt
复制
  $Size += CalcDirectorySize($DirectoryPath . $File . DIRECTORY_SEPARATOR);
代码语言:txt
复制
else
代码语言:txt
复制
  $Size += filesize($DirectoryPath . $File);    

}

closedir($Dir);

return $Size;

}

/*

  • 获取当前页面完整URL地址 */ function get_url() { $sys_protocal = isset($_SERVER'SERVER_PORT') && $_SERVER'SERVER_PORT' == '443' ? 'https://' : 'http://'; $php_self = $_SERVER'PHP_SELF' ? safe_replace($_SERVER'PHP_SELF') : safe_replace($_SERVER'SCRIPT_NAME'); $path_info = isset($_SERVER'PATH_INFO') ? safe_replace($_SERVER'PATH_INFO') : ''; $relate_url = isset($_SERVER'REQUEST_URI') ? safe_replace($_SERVER'REQUEST_URI') : $php_self.(isset($_SERVER'QUERY_STRING') ? '?'.safe_replace($_SERVER'QUERY_STRING') : $path_info); return $sys_protocal.(isset($_SERVER'HTTP_HOST') ? $_SERVER'HTTP_HOST' : '').$relate_url; }

/*

  • 安全过滤函数
  • @parame $string
  • @return string / function safe_replace($string) { $string = str_replace('%20','',$string); $string = str_replace('%27','',$string); $string = str_replace('%2527','',$string); $string = str_replace('','',$string); $string = str_replace('"','"',$string); $string = str_replace("'",'',$string); $string = str_replace('"','',$string); $string = str_replace(';','',$string); $string = str_replace('>','>',$string); $string = str_replace('<','<',$string); $string = str_replace('{','',$string); $string = str_replace('}','',$string); $string = str_replace('\','',$string); return $string; } ?>

下面是接口文件:

api_new.rar

四、调用配置好的站点api.php 文件路径,传入适当参数,就可以实现转换功能。

特别感谢知沃文库系统团队提供的技术指导,同时也欢迎大家指正交流!