共计 16121 个字符,预计需要花费 41 分钟才能阅读完成。
sendFile 发送文件
<?php | |
$doc = filter_input(INPUT_GET, 'file'); | |
if ($doc) { | |
// decode requested file path | |
$docPath = base64_decode($doc); | |
// check file path | |
if ($docPath !== false && file_exists($docPath)) {$mimeType = Utils::get_mime_type($docPath); | |
if (stripos($mimeType, 'audio/') !== false || stripos($mimeType, 'video/') !== false) { | |
// streaming media | |
$stream = new VideoStream($docPath); | |
$stream->start();} else { | |
// output document | |
$fName = basename(filter_input(INPUT_SERVER, 'PATH_INFO')); | |
$fSize = filesize($docPath); | |
if (strpos($fName, '.') === false && strrpos(basename($docPath), '.') !== false) {$ext = substr(basename($docPath), -strrpos(basename($docPath), '.')); | |
$fName .= $ext; | |
} | |
header('Content-type:' . $mimeType); | |
header('Content-disposition: filename="' . $fName . '"'); | |
header('Content-Length:' . $fSize); | |
flush(); | |
$fHandle = fopen($docPath, 'r'); | |
while (!feof($fHandle)) { | |
// send the current file part to the browser | |
print fread($fHandle, 8192); | |
// flush the content to the browser | |
flush();} | |
fclose($fHandle); | |
} | |
} else {header('HTTP/1.0 401 Unauthorized'); | |
echo 'Unauthorized access'; | |
// log | |
$fh = @fopen('getDoc.log', 'a'); | |
if ($fh !== false) { | |
$msg = 'Try to access not existing file'; | |
fwrite($fh, PHP_EOL . date('Y-m-d H:i:s') . '***' . $msg . ' ' . $docPath); | |
fclose($fh); | |
} | |
} | |
} |
videoStream 发送视频流
<?php | |
class VideoStream { | |
private $path = ''; | |
private $stream = null; | |
private $buffer = 102400; | |
private $start = -1; | |
private $end = -1; | |
private $size = 0; | |
/** | |
* @param string $filePath | |
*/ | |
public function setPath($filePath) {$this->path = $filePath;} | |
/** | |
* Open stream | |
*/ | |
private function open() {if (!($this->stream = fopen($this->path, 'rb'))) {die('Could not open stream for reading'); | |
} | |
} | |
/** | |
* Set proper header to serve the video content | |
*/ | |
private function setHeader() {ob_get_clean(); | |
$mimeType = \Utils::get_mime_type($this->path); | |
header("Content-Type:" . $mimeType); | |
header("Cache-Control: max-age=2592000, public"); | |
header("Expires:" . gmdate('D, d M Y H:i:s', time() + 2592000) . 'GMT'); | |
header("Last-Modified:" . gmdate('D, d M Y H:i:s', @filemtime($this->path)) . 'GMT'); | |
$this->start = 0; | |
$this->size = filesize($this->path); | |
$this->end = $this->size - 1; | |
header("Accept-Ranges: 0-" . $this->end); | |
if (isset($_SERVER['HTTP_RANGE'])) { | |
$c_end = $this->end; | |
list(, $range) = explode('=', $_SERVER['HTTP_RANGE'], 2); | |
if (strpos($range, ',') !== false) {header('HTTP/1.1 416 Requested Range Not Satisfiable'); | |
header("Content-Range: bytes $this->start-$this->end/$this->size"); | |
exit; | |
} | |
if ($range == '-') {$c_start = $this->size - substr($range, 1); | |
} else {$range = explode('-', $range); | |
$c_start = $range[0]; | |
$c_end = (isset($range[1]) && is_numeric($range[1])) ? $range[1] : $c_end; | |
} | |
$c_end = ($c_end > $this->end) ? $this->end : $c_end; | |
if ($c_start > $c_end || $c_start > $this->size - 1 || $c_end >= $this->size) {header('HTTP/1.1 416 Requested Range Not Satisfiable'); | |
header("Content-Range: bytes $this->start-$this->end/$this->size"); | |
exit; | |
} | |
$this->start = $c_start; | |
$this->end = $c_end; | |
$length = $this->end - $this->start + 1; | |
fseek($this->stream, $this->start); | |
header('HTTP/1.1 206 Partial Content'); | |
header("Content-Length:" . $length); | |
header("Content-Range: bytes $this->start-$this->end/" . $this->size); | |
} else {header("Content-Length:" . $this->size); | |
} | |
} | |
/** | |
* close currently opened stream | |
*/ | |
private function end() {fclose($this->stream); | |
exit; | |
} | |
/** | |
* perform the streaming of calculated range | |
*/ | |
private function stream() { | |
$i = $this->start; | |
set_time_limit(0); | |
while (!feof($this->stream) && $i <= $this->end) { | |
$bytesToRead = $this->buffer; | |
if (($i + $bytesToRead) > $this->end) {$bytesToRead = $this->end - $i + 1;} | |
$data = fread($this->stream, $bytesToRead); | |
echo $data; | |
flush(); | |
$i += $bytesToRead; | |
} | |
} | |
/** | |
* Start streaming video content | |
*/ | |
public function start() {$this->open(); | |
$this->setHeader(); | |
$this->stream(); | |
$this->end();} | |
} |
sendEmail 发送邮件
<?php | |
$transport = new \Zend\Mail\Transport\Sendmail(); | |
$attachment = array(); | |
// add properties | |
$msg = new \Zend\Mail\Message(); | |
$msg->addFrom('fromEmail', 'fromName') | |
->addTo('toEmail') | |
->setSubject('subject') | |
->addCc('ccEmail') | |
->addBcc('bccEmail'); | |
if (count($attachment) > 0) { | |
// new MIME message | |
$mimeMessage = new \Zend\Mime\Message(); | |
// add body | |
$text = new \Zend\Mime\Part(nl2br('body')); | |
$text->type = \Zend\Mime\Mime::TYPE_HTML; | |
$text->charset = 'utf-8'; | |
$mimeMessage->addPart($text); | |
// add attachment | |
foreach ($attachment as $fPath) {if (file_exists($fPath)) {$attachment = new \Zend\Mime\Part(fopen($fPath, 'r')); | |
$attachment->type = \Zend\Mime\Mime::TYPE_OCTETSTREAM; | |
$attachment->filename = basename($fPath); | |
$attachment->disposition = \Zend\Mime\Mime::DISPOSITION_ATTACHMENT; | |
$attachment->encoding = \Zend\Mime\Mime::ENCODING_BASE64; | |
$mimeMessage->addPart($attachment); | |
} | |
} | |
$msg->setBody($mimeMessage); | |
} else {$msg->setBody('body'); | |
} | |
$transport->send($msg); |
phpexcel 电子表格解决
<?php | |
class Exporter { | |
/** @var string */ | |
public $filename; | |
/** @var string */ | |
public $creator; | |
/** @var string */ | |
public $title; | |
/** @var string */ | |
public $description; | |
/** @var string */ | |
public $subject; | |
/** @var string */ | |
public $keywords; | |
/** @var boolean */ | |
public $boldTitle; | |
/** @var boolean */ | |
public $autoSizeText; | |
/** | |
* @var array | |
* array(<sheet_index> => array('selector' => <cell_selector>,'style' => <PHPExcel_style_array>)) | |
*/ | |
public $cellStyles; | |
public function __construct() {$this->filename = date('Y_m_d_H_i_s', time()) . '.xlsx'; | |
$this->creator = ''; | |
$this->title = ''; | |
$this->description = ''; | |
$this->subject = ''; | |
$this->keywords = ''; | |
$this->boldTitle = false; | |
$this->autoSizeText = false; | |
$this->cellStyles = array();} | |
/** | |
* @param string | |
*/ | |
public function setFilename($fullFilename) {$this->filename = $fullFilename;} | |
/** | |
* @param string | |
*/ | |
public function setCreator($creator) {$this->creator = $creator;} | |
/** | |
* @param string | |
*/ | |
public function setTitle($title) {$this->title = $title;} | |
/** | |
* @param string | |
*/ | |
public function setDescription($description) {$this->description = $description;} | |
/** | |
* @param string | |
*/ | |
public function setSubject($subject) {$this->subject = $subject;} | |
/** | |
* @param string | |
*/ | |
public function setKeywords($keywords) {$this->keywords = $keywords;} | |
/** | |
* @param boolean | |
*/ | |
public function setBoldTitle($boldTitle) {$this->boldTitle = $boldTitle;} | |
/** | |
* @param boolean | |
*/ | |
public function setAutoSizeText($autoSizeText) {$this->autoSizeText = $autoSizeText;} | |
/** | |
* @param array | |
*/ | |
public function setCellStyles($cellStyles) {$this->cellStyles = $cellStyles;} | |
/** | |
* | |
* @param array $sheetItems | |
* @return string filename | |
*/ | |
public function export($sheetItems) { | |
//Generate PHPExcel | |
$excel = new \PHPExcel(); | |
$excel->getProperties() | |
->setCreator($this->creator) | |
->setTitle($this->title) | |
->setDescription($this->description) | |
->setSubject($this->subject) | |
->setKeywords($this->keywords); | |
$idxSheet = 0; | |
$lastColumn = null; | |
foreach ($sheetItems as $sheetName => $items) {if ($idxSheet > 0) {$excel->createSheet($idxSheet); | |
} | |
$currSheet = $excel->setActiveSheetIndex($idxSheet); | |
$currSheet->setTitle(mb_substr($sheetName, 0, 31)); | |
//Fill data | |
$idxRow = 1; | |
foreach ($items as $subDatas) { | |
$idxCol = 0; | |
foreach ($subDatas as $itemValue) {$coords = \PHPExcel_Cell::stringFromColumnIndex($idxCol) . $idxRow; | |
$currSheet->setCellValueExplicit($coords, $itemValue, \PHPExcel_Cell_DataType::TYPE_STRING); | |
$idxCol++; | |
} | |
$idxRow++; | |
} | |
//Style: title bold | |
if ($this->boldTitle) {$lastColumn = $currSheet->getHighestColumn(); | |
$currSheet->getStyle('A1:' . $lastColumn . '1')->applyFromArray(array('font' => array('bold' => true))); | |
} | |
//Style: wrap and autosize text | |
if ($this->autoSizeText) {$lastColumn = ($lastColumn) ? : $currSheet->getHighestColumn(); | |
$currSheet->getStyle('A2:' . $lastColumn . $idxRow)->getAlignment()->setWrapText(true); | |
$iterator = $lastColumn; | |
$iterator++; | |
for ($column = 'A'; $column != $iterator; $column++) {$currSheet->getColumnDimension($column)->setAutoSize(true); | |
} | |
} | |
//Style cells | |
if (count($this->cellStyles) > 0 && isset($this->cellStyles[$idxSheet])) {foreach ($this->cellStyles[$idxSheet] as $row) {$currSheet->getStyle($row['selector'])->applyFromArray($row['style']); | |
} | |
} | |
$currSheet->garbageCollect(); | |
$idxSheet++; | |
} | |
//Save | |
$excel->setActiveSheetIndex(0); | |
$writer = \PHPExcel_IOFactory::createWriter($excel, 'Excel2007'); | |
$writer->save($this->filename); | |
return $this->filename; | |
} | |
} |
ffmpeg 图片批改
<?php | |
/** | |
* exp: Convert video to mp4 | |
* $ffmpeg = new FFMpeg(); | |
* $ffmpeg->open('xxx'); | |
* $ffmpeg->setVcodec('libx264'); | |
* $ffmpeg->setVquality('28'); | |
* $ffmpeg->setAcodec('aac'); | |
* $ffmpeg->setAquality('128k'); | |
* $ffmpeg->setDuration('30'); | |
* $success = $ffmpeg->save('xxx.mp4'); | |
*/ | |
/** | |
* exp: Convert audio to mp3 | |
* $ffmpeg = new FFMpeg(); | |
* $ffmpeg->setAcodec('libmp3lame'); | |
* $ffmpeg->setAquality('6'); | |
* $ffmpeg->setDuration('30'); | |
* $success = $ffmpeg->save('xxx.mp3'); | |
*/ | |
/** | |
* exp: Export screenshot | |
* $ffmpeg = new FFMpeg(); | |
* $ffmpeg->open('xxx.mp4'); | |
* $ffmpeg->setPosition('10'); | |
* $ffmpeg->exportScreenshot('test.png'); | |
*/ | |
/** | |
* exp: avconv -i source_path -codec:v libx264 -crf 28 -codec:a aac -b:a 128k -strict experimental dest_path | |
*/ | |
/** | |
* Class FFMpeg | |
*/ | |
class FFMpeg | |
{ | |
/** | |
* @var bool | |
* Overwrite output files without asking. | |
*/ | |
private $overwrite = true; | |
/** | |
* @var string | |
* file path of (input) | |
*/ | |
private $path = ''; | |
/** | |
* @var string | |
* video codec (output) | |
*/ | |
private $vcodec = ''; | |
/** | |
* @var string | |
* audio codec (output) | |
*/ | |
private $acodec = ''; | |
/** | |
* @var string | |
* duration (output) | |
* | |
* Stop writing the output after its duration reaches duration. | |
* duration may be a number in seconds, or in hh:mm:ss[.xxx] form. | |
*/ | |
private $duration = ''; | |
/** | |
* @var string | |
* quality (output audio) | |
* FOR libmp3lame: 0-9 (a lower value is a higher quality | |
* 0-3 will normally produce transparent results, | |
* 4 (default) should be close to perceptual transparency, | |
* 6 produces an "acceptable" quality.) | |
* FOR OTHERS: bitrate (in bits/s) 128k, 256k | |
*/ | |
private $aquality = ''; | |
/** | |
* @var string | |
* quality (output video) | |
* FOR libx264: 0-51 (0: lossless, 23: default, 51: rubbish, | |
* A value of 18-28 is considered "sane" with 18 being "visually lossless".) | |
* FOR OTHERS: bitrate (in bits/s) 800k, 1000k | |
*/ | |
private $vquality = ''; | |
/** | |
* @var string | |
* position may be either in seconds or in hh:mm:ss[.xxx] form. (input video) | |
*/ | |
private $position = '3'; | |
/** | |
* @var string | |
* This will scale to your desired width | |
* and the height will be automatically scaled to the appropriate value to preserve aspect. | |
*/ | |
private $width = ''; | |
/** | |
* @param string $filePath | |
*/ | |
public function __construct($filePath = '') | |
{$this->path = $filePath;} | |
/** | |
* @param boolean $overwrite | |
*/ | |
public function setOverwrite($overwrite) | |
{$this->overwrite = $overwrite;} | |
/** | |
* @param string $aquality | |
*/ | |
public function setAquality($aquality) | |
{$this->aquality = $aquality;} | |
/** | |
* @param string $vquality | |
*/ | |
public function setVquality($vquality) | |
{$this->vquality = $vquality;} | |
/** | |
* @param string $duration | |
*/ | |
public function setDuration($duration) | |
{$this->duration = $duration;} | |
/** | |
* @param string $filePath | |
*/ | |
public function open($filePath) | |
{$this->path = $filePath;} | |
/** | |
* @param string $acodec | |
*/ | |
public function setAcodec($acodec) | |
{$this->acodec = $acodec;} | |
/** | |
* @param string $vcodec | |
*/ | |
public function setVcodec($vcodec) | |
{$this->vcodec = $vcodec;} | |
/** | |
* @param string $position | |
*/ | |
public function setPosition($position) | |
{$this->position = $position;} | |
/** | |
* @param string $width | |
*/ | |
public function setWidth($width) | |
{$this->width = $width;} | |
/** | |
* @param string $filename | |
* @return bool | |
* @throws \Exception | |
*/ | |
public function save($filename) | |
{if (!file_exists($this->path)) {return false;} | |
//Do ffmpeg command | |
$cmdLine = 'avconv -i' . str_replace('','\ ', $this->path); | |
if ($this->overwrite) {$cmdLine .= '-y';} | |
// video codec | |
if ($this->vcodec !== '') {$cmdLine .= '-codec:v' . $this->vcodec;} | |
// video quality | |
if ($this->vcodec !== ''&& $this->vquality !=='') {if (stripos($this->vcodec, 'libx264') !== false || stripos($this->vcodec, 'h264') !== false) {if ($this->vquality >= 0 && $this->vquality <= 51) {$cmdLine .= '-crf' . $this->vquality; //h264 use -crf} else {throw new \Exception('quality of video: invalid argument (0-51)'); | |
} | |
} else {if (stripos($this->vquality, 'k') !== false) {$cmdLine .= '-b:v' . $this->vquality; // others can user -b:v (bitrate) | |
} else {throw new \Exception('quality of video: invalid argument (128k, 256k...)'); | |
} | |
} | |
} | |
// audio codec | |
if ($this->acodec !== '') {$cmdLine .= '-codec:a' . $this->acodec;} | |
// audio quality | |
if ($this->acodec !== ''&& $this->aquality !=='') {if (stripos($this->acodec, 'libmp3lame') !== false || stripos($this->acodec, 'mp3') !== false) {if ($this->aquality >= 0 && $this->aquality <= 9) {$cmdLine .= '-q:a' . $this->aquality; //mp3 use -qscale:a} else {throw new \Exception('quality of audio: invalid argument (0-9)'); | |
} | |
} else {if (stripos($this->aquality, 'k') !== false) {$cmdLine .= '-b:a' . $this->aquality; // others can user -b:a (bitrate) | |
} else {throw new \Exception('quality of audio: invalid argument (128k, 256k...)'); | |
} | |
} | |
} | |
// ouput maximium duration | |
if ($this->duration !== '') {$cmdLine .= '-t' . $this->duration;} | |
// strict mode | |
$cmdLine .= '-strict experimental' . str_replace('','\ ', $filename); | |
$exec = shell_exec($cmdLine); | |
return ($exec === null); | |
} | |
/** | |
* @param string $imagename | |
* @return bool | |
*/ | |
public function exportScreenshot($imagename) | |
{if (!file_exists($this->path)) {return false;} | |
//Do ffmpeg command | |
$cmdLine = 'avconv -i' . str_replace('','\ ', $this->path); | |
if ($this->overwrite) {$cmdLine .= '-y';} | |
if ($this->position) {$cmdLine .= '-ss' . $this->position;} | |
if ($this->width) {$cmdLine .= '-filter:v scale=' . $this->width . ':-1';} | |
$cmdLine .= '-frames:v 1' . str_replace('','\ ', $imagename); | |
$exec = shell_exec($cmdLine); | |
return ($exec === null); | |
} | |
} |
zip 压缩包
<?php | |
class Zip | |
{ | |
/** @var string */ | |
protected $_encoding; | |
/** @var string */ | |
public $filename; | |
/** | |
* Zip constructor. | |
*/ | |
public function __construct() | |
{$this->setEncoding('CP437//IGNORE//TRANSLIT'); | |
$this->filename = time() . '.zip';} | |
/** | |
* @param string $enc | |
*/ | |
public function setEncoding($enc = null) | |
{$this->_encoding = $enc;} | |
/** | |
* @param string $fullFilename | |
*/ | |
public function setFilename($fullFilename) | |
{$this->filename = $fullFilename;} | |
/** | |
* | |
* @param array $paths string[] | |
* @return boolean TRUE on success, FALSE on failure | |
*/ | |
public function compress($paths) | |
{if (!is_array($paths)) {return false;} | |
// TODO: rename file | |
$cleanPaths = array(); | |
foreach ($paths as $path) {$bName = basename($path); | |
if ($this->_encoding !== null) {$bName = iconv('UTF-8', $this->_encoding, $bName); | |
} | |
$cleanPaths[$path] = $bName; | |
} | |
if (shell_exec('which zip') !== null) {$success = $this->_compressShell($cleanPaths); | |
} else {$success = $this->_compressZipArchive($cleanPaths); | |
} | |
return $success; | |
} | |
/** | |
* @param array $cleanPaths Files to archive. | |
* key: full file path, value: new file name | |
* @return boolean TRUE on success or FALSE on failure. | |
*/ | |
protected function _compressShell($cleanPaths) | |
{ | |
// create temporary working folder | |
$tmpDir = basename($this->filename, '_tmpDir') . '/'; | |
if (is_dir($tmpDir)) {if (!$this->_deleteDir($tmpDir)) {return false;} | |
} | |
if (!mkdir($tmpDir, 0777, true)) {return false;} | |
// copy files to temporary working folder | |
foreach ($cleanPaths as $path => $cleanPath) {copy($path, $tmpDir . $cleanPath); | |
} | |
// zip, 1->compress faster, j->junk (don't record) directory names, q->quiet operation | |
$cmd = 'zip -1jq' . $this->filename . '' . $tmpDir .'*'; | |
$output = array(); | |
exec($cmd, $output, $return); | |
// delete temporary working folder | |
$this->_deleteDir($tmpDir); | |
// return will return non-zero upon an error | |
if (!$return) {return true;} else {return false;} | |
} | |
/** | |
* @param array $cleanPaths Files to archive. | |
* key: full file path, value: new file name | |
* @return boolean TRUE on success or FALSE on failure. | |
*/ | |
protected function _compressZipArchive($cleanPaths) | |
{$zip = new \ZipArchive(); | |
// open zip file | |
$zip->open($this->filename, \ZipArchive::CREATE); | |
// add files, | |
// TODO: improve performance | |
foreach ($cleanPaths as $path => $cleanPath) {$zip->addFile($path, $cleanPath); | |
} | |
// close zip | |
return $zip->close();} | |
/** | |
* @param $dirPath | |
* @return boolean | |
*/ | |
protected function _deleteDir($dirPath) | |
{if (!is_dir($dirPath)) {return false;} | |
if (substr($dirPath, strlen($dirPath) - 1, 1) != '/') {$dirPath .= '/';} | |
foreach (glob($dirPath . '*', GLOB_MARK) as $file) {if (is_dir($file)) {$this->_deleteDir($file); | |
} else {unlink($file); | |
} | |
} | |
return rmdir($dirPath); | |
} | |
/** | |
* @param string $destination | |
* @param array $entries | |
* @return boolean | |
*/ | |
public function deCompress($destination, $entries = null) | |
{$zip = new \ZipArchive(); | |
$zip->open($this->filename, \ZipArchive::CREATE); | |
$res = $zip->extractTo($destination, $entries = null); | |
$zip->close(); | |
return $res; | |
} | |
} |
utils 工具函数
<?php | |
/** | |
* Get memory usage | |
* @return string | |
*/ | |
public static | |
function get_memory_usage() {$mem_usage = memory_get_peak_usage(true); | |
if ($mem_usage < 1024) {return $mem_usage . "bytes";} | |
elseif($mem_usage < 1048576) {return round($mem_usage / 1024, 2) . "KB"; | |
} else {return round($mem_usage / 1048576, 2) . "MB"; | |
} | |
} | |
/** | |
* Detemine is JSON and decode JSON | |
* @param string $json | |
* @param bool $return_data | |
* @return mixed the formed array or true on success, or false on failure | |
*/ | |
public static function is_json($json, $return_data = false) {$data = json_decode($json, true); | |
return (json_last_error() == JSON_ERROR_NONE) ? ($return_data ? $data : TRUE) : FALSE; | |
} | |
/** | |
* Set ini memory limit | |
* @param mixed $newV string '1024M' or int 1024 | |
* @return string the old value on success, false on failure. | |
*/ | |
public static function ini_set_memory_limit($newV) {$newVInt = (int)str_ireplace('M', '', (string)$newV); | |
$oldV = ini_get('memory_limit'); | |
$oldVInt = (int)str_ireplace('M', '', (string)$oldV); | |
if ($oldVInt < $newVInt) {return ini_set('memory_limit', $newVInt . 'M'); | |
} | |
return $oldV; | |
} | |
/** | |
* Get mine type of file | |
* @param string $filename | |
* @return mixed the mine type on success, or false on failure | |
*/ | |
public static function get_mime_type($filename) {$realpath = realpath($filename); | |
if($realpath) {if (function_exists('finfo_file') && function_exists('finfo_open') && defined('FILEINFO_MIME_TYPE')) {$finfo = finfo_open(FILEINFO_MIME_TYPE); | |
$mimetype = finfo_file($finfo, $realpath); | |
finfo_close($finfo); | |
return $mimetype; | |
} | |
if (function_exists('mime_content_type')) {return mime_content_type($realpath); | |
} | |
} | |
return false; | |
} |
正文完