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 ();
}
}

