2024-08-31 01:03:37 +08:00

174 lines
6.3 KiB
PHP
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* 通过libreoffice转换office文件为pdf
*
* 启动进程:
* /usr/lib64/libreoffice/program/soffice --headless --accept="socket,host=127.0.0.1,port=8100;urp;" --nofirststartwizard &
* 转换文件:
* /usr/lib64/libreoffice/program/soffice --headless --invisible --convert-to pdf --outdir 输出目录 源文件
*
* https://blog.csdn.net/weixin_40816738/article/details/103890765
* https://gblfy.blog.csdn.net/article/details/103861905
*
* https://www.cnblogs.com/xcp19870712/p/4760842.html?_t_t_t=0.4833811022118151
*/
class officeViewerlibreOfficeIndex extends Controller {
public function __construct() {
parent::__construct();
$this->pluginName = 'officeViewerPlugin';
}
public function index(){
$plugin = Action($this->pluginName);
if(!$plugin->allowExt('lb')) {
$plugin->showTips(LNG('officeViewer.main.invalidExt'), 'LibreOffice');
}
if(!$this->getSoffice()){
$plugin->showTips(LNG('officeViewer.libreOffice.sofficeError'), 'LibreOffice');
}
$path = $plugin->filePath($this->in['path']);
$info = IO::info($path);
$ext = $info['ext'];
// 转换文件已存在,直接输出
$fileHash = KodIO::hashPath($info);
$convName = "libreOffice_{$ext}_{$fileHash}.pdf";
if (!is_dir(TEMP_FILES)) mk_dir(TEMP_FILES);
$tempFile = TEMP_FILES . $convName;
$tempInfo = IO::infoFull($plugin->cachePath.$convName);
if ($tempInfo) {
$file = Model('File')->fileInfo($tempInfo['fileID']);
if ($file && IO::exist($file['path'])) {
return $this->fileView($tempInfo['path'],$convName);
}
}
$localFile = $this->localFile($path);
if(!$localFile){
$localFile = $plugin->pluginLocalFile($path); // 下载到本地文件
}
// 后缀名异常时webdav为tmp会转换失败
if (get_path_ext($localFile) != $ext) {
$localFile = $localFileNew = IO::copyFile($localFile, $localFile.'.'.$ext);
}
$this->convert2pdf($localFile,$tempFile,$ext);
if (isset($localFileNew)) del_file($localFileNew);
if(@file_exists($tempFile)){
$cachePath = IO::move($tempFile,$plugin->cachePath);
Cache::set('libreOffice_pdf_'.$fileHash,'yes');
return $this->fileView($cachePath,$convName);
}
Cache::set('libreOffice_pdf_'.$fileHash,'no');
del_file($tempFile);
$plugin->showTips(LNG('officeViewer.libreOffice.convertError'), 'LibreOffice');
}
// 打开pdf文件
public function fileView($path,$convName){
// $this->in['path'] = Action('explorer.share')->linkFile($path).'&path=/'.$convName;
$link = Action('explorer.share')->linkFile($path).'&path=/'.$convName;
$link = APP_HOST.'#fileView&path='. rawurlencode($link);
Action($this->pluginName)->showWebOffice('lb', $link);
// Action('explorer.fileView')->index();
}
// office文件转pdf
private function convert2pdf($file,$cacheFile,$ext){
$command = $this->getSoffice();
if(!$command){
Action($this->pluginName)->showTips(LNG('officeViewer.libreOffice.sofficeError'), 'LibreOffice');
}
//linux下$cacheFile不可写问题先生成到/tmp下;再复制出来
$tempPath = $cacheFile;
if($GLOBALS['config']['systemOS'] == 'linux' && is_writable('/tmp/')){
mk_dir('/tmp/libreOffice');
$tempPath = '/tmp/libreOffice/'.rand_string(15).'.pdf';
}
$fname = get_path_this($tempPath);
$fpath = get_path_father($tempPath);
// 转换类型'pdf'改为'新文件名.pdf',会生成'源文件名.新文件名.pdf'
$this->setLctype($fname,$file);
$export = 'export HOME=/tmp/libreOffice && ';
$script = $export.$command . ' --headless --invisible --convert-to '.escapeShell($fname).' '.escapeShell($file).' --outdir '.$fpath;
$out = shell_exec($script);
$tname = substr(end(explode('/', $file)), 0, -strlen('.'.$ext));
$tfile = $fpath . $tname . '.' . $fname; // 源文件名.filename.pdf
if(!file_exists($tfile)){
write_log('libreoffice convert error: '.$script."\n".$out,'error');
}
$res = move_path($tfile,$cacheFile);
if (!$res) write_log('libreoffice move file error: '.$tfile.'=>'.$cacheFile, 'error');
}
// 设置地区字符集,避免中文被过滤
private function setLctype($path,$path2=''){
if (stripos(setlocale(LC_CTYPE, 0), 'utf-8') !== false) return;
if (Input::check($path,'hasChinese') || ($path2 && Input::check($path2,'hasChinese'))) {
setlocale(LC_CTYPE, "en_US.UTF-8");
}
}
// 获取文件 hash
private function localFile($path){
$pathParse = KodIO::parse($path);
if(!$pathParse['type']) return $path;
$fileInfo = IO::info($path);
if($fileInfo['fileID']){
$tempInfo = Model('File')->fileInfo($fileInfo['fileID']);
$fileInfo = IO::info($tempInfo['path']);
$pathParse = KodIO::parse($tempInfo['path']);
}
$parent = array('path'=>'{userFav}/');
$fileInfo = Action('explorer.listDriver')->parsePathIO($fileInfo,$parent);
if($fileInfo['ioDriver'] == 'Local' && $fileInfo['ioBasePath']){
$base = rtrim($fileInfo['ioBasePath'],'/');
if(substr($base,0,2) == './') {
$base = substr_replace($base, BASIC_PATH, 0, 2);
}
return $base . '/' . ltrim($pathParse['param'], '/');
}
return false;
}
//linux 注意修改获取bin文件的权限问题;
public function check(){
KodUser::checkRoot();
$bin = $this->in['soffice'];
$plugin = Action($this->pluginName);
if(!empty($bin)) {
$plugin->setConfig(array('lbSoffice' => $bin));
}
if(isset($_GET['check'])){
if(!function_exists('shell_exec')) {
show_json(LNG('officeViewer.libreOffice.execDisabled'), false);
}
$msg = '';
if(!$soffice = $this->getSoffice()) {
$msg = LNG('officeViewer.libreOffice.checkError');
}
show_json($msg, !!$soffice);
}
Action($this->pluginName)->includeTpl('static/libreoffice/check.html');
}
// 获取soffice路径
public function getSoffice(){
$check = 'LibreOffice';
$data = Action($this->pluginName)->_appConfig('lb');
$bin = isset($data['soffice']) ? $data['soffice'] : '';
$bin = escapeShell(iconv_system($bin)); // win路径空格处理
$result = $this->checkBin($bin,$check);
return $result ? $bin : false;
}
private function checkBin($bin,$check){
$code = Cache::get($bin);
if ($code) return $code;
$result = shell_exec($bin.' --help'); // ' 2>&1'
$code = strstr($result,$check) ? true : false;
Cache::set($bin, $code);
return $code;
}
}