Qupload + 多种素材转换成图片实现 (psd,cdr,ai,png,jpg,gif,zip,rar,ppt,pptx,pdf,mp4,avi,mov)

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

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注