ppt如果直接openoffice解析成pdf再转图片,会有错位问题. 暂时只发现可以通过python调用wps实现兼容的解析.
<?php class QuploadController extends CController { /** * 首页 */ protected function beforeAction($action) { return true; } function actionDemo() { $this->renderPartial ( 'demo' ); } function log($params = []) { write_log ( 'qupload', $params ); } function actionToken() { $u = lib ( 'qupload/base.php' ); $file_format = preg_replace ( '/^.+\.(\w+)$/ims', '\\1', $_GET ['name'] ); $file_format = strtolower ( $file_format ); if (! in_array ( $file_format, [ 'psd', 'cdr', 'ai', 'png', 'jpg', 'gif', 'zip', 'rar', 'ppt', 'pptx', 'pdf', 'mp4', 'avi', 'mov' ] )) { die ( 'do not allow the file format.' ); } $token = $u->genToken ( $_GET ['name'], $_GET ['size'], $_GET ['time'] ); if ($token) { if ($_GET ['size'] > 4 * 1000 * 1000 * 1000) { $result = json_encode ( array ( 'token' => $token, 'range' => implode ( '-', $u->getRange ( $token ) ), 'status' => $u->getStatus ( $token ), 'tmp_dir' => $u->getInterval (), 'status' => 2, 'error_msg' => '文件大小不能超过1G' ) ); $this->log ( $result ); echo $result; exit (); } $status = $u->getStatus ( $token ); if ($status === 2) { // 上传成功 try { list ( $images_list, $file_info ) = $this->parseImglist ( $u->getInterval () . '/' . $token ); $error_msg = "success"; } catch ( Exception $e ) { $error_msg = $e->getMessage (); } } $result = json_encode ( array ( 'token' => $token, 'range' => implode ( '-', $u->getRange ( $token ) ), 'status' => $u->getStatus ( $token ), 'tmp_dir' => $u->getInterval (), 'error_msg' => $error_msg, 'images_list' => $images_list ) ); $this->log ( $result ); echo $result; exit (); } } public static function uploadDir() { return UPLOAD_DIR . 'file/'; } public static function uploadUrl() { return UPLOAD_URL . 'file/'; } function actionDownload() { // 弃用,上传成功,根据文件路径,将文件重命名 // 上传时,需要检测当前用户是否登录. // exit (); // $_REQUEST ['file'] = '17625/3344abdedd12a65dc7f78d991338d95c4558f66f'; // $_REQUEST ['file'] = '17625/050f98d89455c3e6e4c6f96f8d1f7dc8b43b5e70'; $file = urldecode ( $_REQUEST ['file'] ); if (! preg_match ( '/^\/?\d+\/\w+\.\w+$/ims', $file )) { die ( 'the filename is error' ); } $filePath = UPLOAD_DIR . 'file/' . $file; if (! file_exists ( $filePath )) { die ( 'the file do not exists' ); } if (! file_exists ( $filePath . '.json' )) { die ( 'the file json do not exists' ); } $file_info = file_get_contents ( $filePath . '.json' ); $file_info = json_decode ( $file_info, true ); if (! $file_info) { die ( 'the file json is error' ); } $filename = $file_info ['name']; header ( 'Content-Description: File Transfer' ); header ( 'Content-Type: application/octet-stream' ); $ua = $_SERVER ["HTTP_USER_AGENT"]; if (preg_match ( '/MSIE/', $ua )) { header ( 'Content-Disposition: attachment; filename="' . rawurlencode ( $filename ) . '"' ); } elseif (preg_match ( "/Firefox/", $ua )) { header ( 'Content-Disposition: attachment; filename*="utf8\'\'' . $filename . '"' ); } else { header ( 'Content-Disposition: attachment; filename="' . $filename . '"' ); } header ( 'Content-Transfer-Encoding: binary' ); header ( 'Expires: 0' ); header ( 'Cache-Control: must-revalidate, post-check=0, pre-check=0' ); header ( 'Pragma: public' ); header ( 'Content-Length: ' . filesize ( $filePath ) ); set_time_limit ( 300 ); // 避免下载超时 ob_end_clean (); // 避免大文件导致超过 memory_limit 限制 readfile ( $filePath ); } public function actionFetch_img_list() { $u = lib ( 'qupload/base.php' ); $token = $_REQUEST ['token']; $status = $u->getStatus ( $token ); if ($status == 2) { $error_msg = 'success'; } else { $error_msg = 'error'; } $img_dir = Article::uploadFileDir () . $u->getInterval () . '/' . $token . '_img/'; $img_list = FileTools::getCurList ( $img_dir, array ( '/\.(png|jpg|gif)$/i' => false ) ); if (empty ( $img_list )) { throw new Exception ( "[{$token}]获取图片异常" ); } // ppt 解析出所有图片 $images_list = [ ]; $dir = str_replace ( '\\', '/', WWW_DIR ); foreach ( $img_list as $img ) { $img = str_replace ( '\\', '/', $img ); $img = str_replace ( $dir, '', $img ); $images_list [] = $img; } echo json_encode ( array ( 'token' => $token, 'range' => implode ( '-', $u->getRange ( $token ) ), 'status' => $status, 'tmp_dir' => $u->getInterval (), 'error_msg' => $error_msg, 'images_list' => $images_list ) ); } function actionUpload() { set_time_limit ( 0 ); ignore_user_abort ( true ); $u = lib ( 'qupload/base.php' ); $token = isset ( $_GET ['token'] ) ? $_GET ['token'] : null; $start = isset ( $_GET ['start'] ) ? ( int ) $_GET ['start'] : null; if ($start > 4 * 1000 * 1000 * 1000) { $msg = 'do not allow the size more than 1GB'; $this->log ( [ $msg, $_GET ] ); die ( $msg ); } if (! $info = $u->getTokenInfo ( $token )) { $msg = 'can not get the token info'; $this->log ( [ $msg, $_GET ] ); die ( $msg ); } $fp = fopen ( 'php://input', 'r' ); $size = $u->size ( $token ); // 如果上传起始位置大于文件位置 肯定失败 if ($start > $size) { $this->log ( [ 'position is wrong', $_GET ] ); exit ( 0 ); } // 如果文件已经存在 那么肯定是添加 if ($size > 0) { $u->append ( $token, $fp, $start ); } else { $u->store ( $token, $fp ); } $status = $u->getStatus ( $token ); $images_list = [ ]; if ($status === 3) { $u->delete ( $token ); // 上传出错,清理标记,重新上传 $status = 0; } elseif ($status === 2) { // 上传成功 try { list ( $images_list, $file_info ) = $this->parseImglist ( $u->getInterval () . '/' . $token ); $error_msg = "success"; } catch ( Exception $e ) { $error_msg = $e->getMessage (); } } else { // status=1 // 上传中 } $result = json_encode ( array ( 'range' => implode ( '-', $u->getRange ( $token ) ), 'status' => $status, 'tmp_dir' => $u->getInterval (), 'token' => $token, 'error_msg' => $error_msg, 'images_list' => $images_list ) ); $this->log ( $result ); echo $result; } function parseImglist($upload_file) { $file_path = UPLOAD_DIR . '/file/' . $upload_file; if (! file_exists ( $file_path )) { sjson ( false, $title, '文件不存在' ); } $file_info = file_get_contents ( $file_path . '.json' ); $file_info = json_decode ( $file_info, true ); if (! $file_info) { sjson ( false, $title, '文件信息异常' ); } $file_format = preg_replace ( '/^.+\.(\w+)$/ims', '\\1', $file_info ['name'] ); $file_format = strtolower ( $file_format ); $file_flag = preg_replace ( '/^\w+\/(\w+\.\w+)$/ims', '\\1', $upload_file ); $file_path_with_format = $file_path . $file_format; // 如果为图片,直接复制图片到指定目录 $img_dir = $file_path . '_img'; if (file_exists ( $img_dir )) { lib ( 'FileSystem.php' ); // 如果目录已经存在,删除,再进行命令调用. // 不然容易出现是否覆盖的提示,导致脚本异常 rmdirs ( $img_dir ); } mkdir ( $img_dir, 0777 ); // 复制文件,并做解析处理,如果防止出现异常时,需要进行二次提交 if (in_array ( $file_format, [ 'psd', 'cdr', 'ai', 'png', 'jpg', 'gif', 'zip', 'rar' ] )) { // 只有图片允许压缩包 // psd,cdr,ai,png,jpg,gif,zip // sjson ( false, $title, '平面设计只允许上传psd,cdr,ai,png,jpg,gif,zip<br>不能' . $file_format ); if (in_array ( $file_format, [ 'zip', 'rar' ] )) { // 先获取压缩包文件内容,检查格式是否包含在指定列表中 if ($file_format == 'zip') { $command = "unzip -l {$file_path}"; } else { $command = "unrar v {$file_path}"; } list ( $val, $output, $result ) = $this->runCommand ( $command, "[{$upload_file}]压缩包内容获取异常" ); // 不管压缩包格式是rar 还是 zip 获取内容列表时,都是 // ----- // .... // --------- $begin_file_content = 0; foreach ( $output as $line ) { if (stristr ( $line, '----' )) { $begin_file_content ++; continue; } if ($begin_file_content == 1) { $img_format = preg_replace ( '/^.+\.(\w+)$/ims', '\\1', $line ); if (! in_array ( $img_format, [ 'psd', 'cdr', 'ai', 'png', 'jpg', 'gif' ] )) { throw new Exception ( "[{$upload_file}]压缩包文件内容格式异常." ); } } elseif ($begin_file_content == 2) { break; } } if ($file_format == 'zip') { $command = "unzip {$file_path} -d {$img_dir}"; } else { $command = "unrar x {$file_path} {$img_dir}"; } list ( $val, $output, $result ) = $this->runCommand ( $command, "[{$upload_file}]压缩包解压异常" ); $file_list = FileTools::getCurList ( $img_dir, array ( '/\.(png|jpg|gif|ai|cdr|psd)$/i' => false ) ); if (empty ( $file_list )) { throw new Exception ( "[{$upload_file}]获取压缩包内容异常" ); } // ppt 解析出所有图片 $images_list = [ ]; foreach ( $file_list as $file ) { $format = preg_replace ( '/^.+\.(\w+)$/ims', '\\1', $file ); if (in_array ( $format, [ 'psd', 'ai' ] )) { // 通过命令将文件转成图片 $command = "convert {$file}[0] {$file}.png"; list ( $val, $output, $result ) = $this->runCommand ( $command, "[{$upload_file}]图片[{$format}]转化异常" ); $file = $file . '.png'; } elseif (in_array ( $format, [ 'cdr' ] )) { // cdr 格式比较特殊 // 通过命令将文件转成图片 $_pdf_file = "{$file}.pdf"; $command = "uniconvertor {$file} {$_pdf_file}"; list ( $val, $output, $result ) = $this->runCommand ( $command, "[{$upload_file}]cdr图片转化pdf异常" ); $command = "convert {$_pdf_file} {$_pdf_file}.png"; list ( $val, $output, $result ) = $this->runCommand ( $command, "[{$upload_file}]cdr图片转化pdf解析成图片异常" ); $file = $_pdf_file . '.png'; } $images_list [] = preg_replace ( '/\/data\/www\/sucai\/www/ims', '', $file ); } } elseif (in_array ( $file_format, [ 'png', 'jpg', 'gif' ] )) { // 如果为图片,直接复制图片到指定目录 $img_path = $img_dir . '/' . $file_flag; copy ( $file_path, $img_path ); $images_list [] = Article::uploadFileUrl () . $upload_file . '_img/' . $file_flag; } elseif (in_array ( $file_format, [ 'psd', 'ai' ] )) { // 通过命令将文件转成图片 $img_path = $upload_file . '_img/' . $file_flag . '.png'; $command = "convert {$file_path}[0] " . Article::uploadFileDir () . $img_path; list ( $val, $output, $result ) = $this->runCommand ( $command, "[{$upload_file}]图片转化异常" ); $images_list [] = Article::uploadFileUrl () . $img_path; } elseif (in_array ( $file_format, [ 'cdr' ] )) { // cdr 格式比较特殊 // 通过命令将文件转成图片 $_pdf_file = "{$img_dir}{$file_flag}.pdf"; $command = "uniconvertor {$file_path} {$_pdf_file}"; list ( $val, $output, $result ) = $this->runCommand ( $command, "[{$upload_file}]cdr图片转化pdf异常" ); $command = "convert {$_pdf_file} {$_pdf_file}.png"; list ( $val, $output, $result ) = $this->runCommand ( $command, "[{$upload_file}]cdr图片转化pdf解析成图片异常" ); $images_list [] = preg_replace ( '/\/data\/www\/sucai\/www/ims', '', "{$_pdf_file}.png" ); } } elseif (in_array ( $file_format, [ 'ppt', 'pptx' ] )) { $jod_dir = EXT_DIR . '/convert_tools/'; // sjson ( false, $title, 'PPT模板只允许上传ppt,pptx' ); $command = "convert {$file_path}[0] " . Article::uploadFileDir () . $img_path; $pdf_file = $img_dir . '/' . $file_flag . '.pdf'; // ppt to pdf $command = "java -jar {$jod_dir}jodconverter/lib/jodconverter-cli-2.2.2.jar {$file_path} {$pdf_file}"; list ( $val, $output, $result ) = $this->runCommand ( $command, "[{$upload_file}]ppt转pdf异常" ); // pdf to png $command = "convert {$pdf_file} {$pdf_file}.png"; list ( $val, $output, $result ) = $this->runCommand ( $command, "[{$upload_file}]pdf转图片异常" ); $img_list = FileTools::getCurList ( $img_dir, array ( '/\.png$/i' => false ) ); if (empty ( $img_list )) { throw new Exception ( "[{$upload_file}]获取图片异常" ); } // ppt 解析出所有图片 $images_list = [ ]; foreach ( $img_list as $img ) { $images_list [] = preg_replace ( '/\/data\/www\/sucai\/www/ims', '', $img ); } } elseif (in_array ( $file_format, [ 'pdf' ] )) { // pdf to png $command = "convert {$file_path} {$img_dir}/{$file_flag}.png"; list ( $val, $output, $result ) = $this->runCommand ( $command, "[{$upload_file}]pdf转图片异常" ); $img_list = FileTools::getCurList ( $img_dir, array ( '/\.png$/i' => false ) ); if (empty ( $img_list )) { throw new Exception ( "[{$upload_file}]获取图片异常" ); } // ppt 解析出所有图片 $images_list = [ ]; foreach ( $img_list as $img ) { $images_list [] = preg_replace ( '/\/data\/www\/sucai\/www/ims', '', $img ); } } else if (in_array ( $file_format, [ 'mp4', 'avi', 'mov' ] )) { // 视频 mp4,avi,mov // sjson ( false, $title, '视频编辑只允许上传mp4,avi,mov' ); // 获取视频总长度 $file_length = $this->getVideoLength ( $file_path ); if ($file_length < 10) { // 视频长度小于10秒,只获取一张图片, $file_img_spans = [ 0 ]; } else { // 每10分之一长度的地方进行图片采集 $file_img_span = intval ( $file_length / 10 ); while ( ($left_file_length += $file_img_span) <= $file_length ) { $file_img_spans [] = $left_file_length; } } foreach ( $file_img_spans as $time_span ) { $img = "{$img_dir}/{$file_flag}-{$time_span}.png"; // 小于0.1容易生成空白图片,提示缓存异常啥的 $command = "ffmpeg -ss {$time_span} -t 0.1 -i {$file_path} -y -f mjpeg {$img}"; list ( $val, $output, $result ) = $this->runCommand ( $command, "[{$upload_file}]视频提取图片[{$time_span}]异常" ); } $img_list = FileTools::getCurList ( $img_dir, array ( '/\.png$/i' => false ) ); if (empty ( $img_list )) { throw new Exception ( "[{$upload_file}]获取图片异常" ); } // ppt 解析出所有图片 $images_list = [ ]; foreach ( $img_list as $img ) { chmod ( $img, 0777 ); $images_list [] = preg_replace ( '/\/data\/www\/sucai\/www/ims', '', $img ); } } else { die ( "[{$upload_file}]上传文件格式异常" ); } return [ $images_list, $file_info ]; } /** * * @param unknown $command * @return string[ $val,//异常状态标记,通常0表示正常 * $output,//命令执行结果 * $result//最后一句命令返回 * ] */ function runCommand($command, $msg = '') { $output = ""; $val = ""; // $val=0 表示正常 // 需要标记 ' 2>&1' 将屏幕输出内容(包括异常)全部进行反馈,不加会返回空 $result = exec ( $command . ' 2>&1', $output, $val ); if ($val) { // gddebug ( $command, $val, $output, $result ); write_log ( 'runcommand', [ $command, $val, $output, $result ] ); throw new Exception ( $msg ); } return [ $val, $output, $result ]; } function getVideoLength($file) { if (! file_exists ( $file )) { throw new Exception ( "file do not exists" ); } $dir = dirname ( $file ); $command = "ffmpeg -i {$file} 2>&1"; $output = ""; $val = ""; $result = exec ( $command, $output, $val ); foreach ( $output as $line ) { if (preg_match ( '/Duration\: (\d+(?:\.\d+)?):(\d+(?:\.\d+)?):(\d+(?:\.\d+)?)\, start/ims', $line, $match )) { $second = intval ( $match [1] ) * 60 * 60 + intval ( $match [2] ) * 60 + intval ( $match [3] ); return $second; } } throw new Exception ( "识别不到视频,请检查 result 变量内容" ); } function actionIndex() { exit (); } }