php版照片按拍照日期归类整理源码

  • php版照片按拍照日期归类整理源码
  • 以年-月为目录进行归类
  • 跳过重复文件
  • 视频文件、非图片文件单独归类
  • 读不到日期的照片单独归类

<?php
/*
	2014/4/1 17:27 klggg 照片按拍照日期整理
	依赖 php_exif 扩展
	 win下打开扩展
	   extension=php_exif.dll      ; 注,这段必须放在 extension=php_mbstring.dll 下面

*/
date_default_timezone_set('PRC');
//require dirname(__FILE__).'/vendor/autoload.php';

$curr_dir_path = dirname(__FILE__); 

//要处理的照片来源路径  * 需要针对自己的情况做下修改
$photo_source_path = 'K:/家庭照片';

$config =  array(
	'fileExtension' => array(
		//图片的扩展名
		'pic' => array('jpg','png','gif','bmp'),
		//视频的扩展名
		'movies' => array('mov','3gp','mp4')
	),
	'path'  => array(
		//所有新目录产生的根目录,* 注意修改成自己的路径
		'root' => $curr_dir_path.'/pic_new_month'
		)
);

$config['path']['pic'] = $config['path']['root'].'/pic';	//照片移到哪个目录
$config['path']['movies'] = $config['path']['root'].'/movies';	//视频移到哪个目录
$config['path']['unkown'] = $config['path']['root'].'/unkown';	//非照片文件移到哪个目录

//初始化log相关
$log_path = $config['path']['root'].'/log/';
if(!is_dir($log_path))
        mkdir($log_path, 0755, true);
$log_file = $log_path.'/'.date('Y-m-d').'.log';

$log_category = 'PhotoMove';

$log =null;
$log_config = array('locking' => 1,'buffering' => true, 'lineFormat' =>'%1$s %2$s [%3$s] %8$s->%7$s  %6$s  %4$s');
if(!defined('PEAR_LOG_DEBUG'))
{
	define('PEAR_LOG_EMERG',    0);     /* System is unusable */
	define('PEAR_LOG_ALERT',    1);     /* Immediate action required */
	define('PEAR_LOG_CRIT',     2);     /* Critical conditions */
	define('PEAR_LOG_ERR',      3);     /* Error conditions */
	define('PEAR_LOG_WARNING',  4);     /* Warning conditions */
	define('PEAR_LOG_NOTICE',   5);     /* Normal but significant */
	define('PEAR_LOG_INFO',     6);     /* Informational */
	define('PEAR_LOG_DEBUG',    7);     /* Debug-level messages */

	$log = DefaultLog::singleton("file"
			, $log_file,$log_category
			, $log_config
			,PEAR_LOG_DEBUG);
}
else
{
	$log = Log::singleton("file"
			, $log_file,$log_category
			, $log_config
			,PEAR_LOG_DEBUG);
}

$PhotoMove_obj=  new PhotoMove($config,$log);
$PhotoMove_obj->run($photo_source_path);
echo "done";

class PhotoMove {

	private $mRootPath= './tmp';

	private $logger= null;

	private $mConfig= Array();

	public function  __construct($config,$logger) {

		$this->mConfig = $config;
		$this->mRootPath = $config['path']['root'];

		foreach($config['path'] as $tmp_path)
		{
			if(!is_dir($tmp_path))
				mkdir($tmp_path, 0755, true);
		}

		$this->logger = $logger;
	}

	/**
	 * 运行脚本入口
	 * @param string $srcPath 照片来源目录
	 *
	 */
	public function  run($srcPath) {

		$it = new RecursiveDirectoryIterator($srcPath);

		foreach (new RecursiveIteratorIterator($it, 2) as $file_path) {

			if ($file_path->isDir())
				continue;

			$file_path_name = $file_path->__toString();
			$this->logger->info('file_path_name: '.$file_path_name);
			$file_info =	pathinfo($file_path_name);
			if('thumbs.db' == strtolower($file_info['basename']))
				continue;

			if(!isset($file_info['extension']))
			{
				$this->logger->notice('no extension : '.$file_path_name);
				$file_info['extension'] = '';
			}
			$file_info['extension'] = strtolower($file_info['extension']);
			//找到图片
			if(in_array($file_info['extension'],$this->mConfig['fileExtension']['pic']))
			{
				$tmp_timestamp = $this->getDateTimeOriginal($file_path_name);

				//移到新目录
				$new_dir = $this->mConfig['path']['pic'].'/'.date('Y-m',$tmp_timestamp);
				if(!is_dir($new_dir))
					mkdir($new_dir, 0755, true);
				$tmp_new_file_path = $new_dir.'/'.$file_info['basename'];

				$this->move($file_path_name,$tmp_new_file_path);

			}
			else if(in_array($file_info['extension'],$this->mConfig['fileExtension']['movies']))
			{
				$tmp_new_file_path = $this->mConfig['path']['movies'].'/'.$file_info['basename'];
				$this->move($file_path_name,$tmp_new_file_path);
			}
			else
			{
				//非图片文件处理
				$this->logger->notice('not image file : '.$file_path_name);
				$tmp_new_file_path = $this->mConfig['path']['unkown'].'/'.$file_info['basename'];
				$this->move($file_path_name, $tmp_new_file_path);
			}
		}

	}

	/**
	 * 取拍照日期
	 * @param string $filePathName 照片完整路径
	 * @param string $defaultDateTime 取不到拍照时间时的默认时间
	 * @return  int 返回时间戳
	 *
	 */
	public function  getDateTimeOriginal($filePathName,$defaultDateTime='1970:01:01 01:01:01') {

		$exif = exif_read_data($filePathName, 0, true);
		$date_time_original = $defaultDateTime;
		if(empty($exif['EXIF']) || empty($exif['EXIF']['DateTimeOriginal']))
		{
			$this->logger->warning("empty DateTimeOriginal");
		}
		else
			$date_time_original = $exif['EXIF']['DateTimeOriginal']; 	   //string(19) "2011:03:13 10:23:09"

		$this->logger->info('DateTimeOriginal: '.$date_time_original);

		$tmp_timestamp  = strtotime($date_time_original);
		return $tmp_timestamp;
	}

	/**
	 * 移动文件
	 * @param string $oldFilePath 原文件完整路径
	 * @param string $newFilePath 目标文件完整路径
	 * @return  bool
	 *
	 */
	public function  move($oldFilePath,$newFilePath) {

		//针对已存在的文件
		if(file_exists($newFilePath))
		{
			$this->logger->notice("file_exists ".$newFilePath);
			return false;
		}
		$result = false;
//		if($result == copy($oldFilePath, $newFilePath))
		if($result == rename($oldFilePath, $newFilePath))
			$this->logger->err("rename false, to  ".$newFilePath );
		else
			$this->logger->info('[ok] move  '.$oldFilePath.' to '.$newFilePath);

		return $result;

	}

}

class DefaultLog {
    var $_formatMap = array('%{timestamp}'  => '%1$s',
                            '%{ident}'      => '%2$s',
                            '%{priority}'   => '%3$s',
                            '%{message}'    => '%4$s',
                            '%{file}'       => '%5$s',
                            '%{line}'       => '%6$s',
                            '%{function}'   => '%7$s',
                            '%{class}'      => '%8$s',
                            '%\{'           => '%%{');

    var $_lineFormat = '%1$s %2$s [%3$s] %4$s';

    var $_timeFormat = '%b %d %H:%M:%S';

    var $_eol = "\n";
    var $_dirmode = 0755;

	private $_filename= './tmp';
    var $_backtrace_depth = 0;

	public function  __construct($name, $ident, $conf, $level='') {

        $this->_filename = $name;
        $this->_ident = $ident;

        if (!empty($conf['lineFormat'])) {
            $this->_lineFormat = str_replace(array_keys($this->_formatMap),
                                             array_values($this->_formatMap),
                                             $conf['lineFormat']);
        }

		if (!is_dir(dirname($this->_filename))) {
			mkdir(dirname($this->_filename, $this->_dirmode,true));
		}

	}
    public static function singleton($handler, $name = '', $ident = '',
                                     $conf = array(), $level = PEAR_LOG_DEBUG)
    {
        static $instances;
        if (!isset($instances)) $instances = array();

        $signature = serialize(array($handler, $name, $ident, $conf, $level));
        if (!isset($instances[$signature])) {
			 $instances[$signature] =  new self($name, $ident, $conf, $level);

        }

        return $instances[$signature];
    }

    function log($message, $priority = null)
    {

		/* Extract the string representation of the message. */
        $message = $this->_extractMessage($message);

        /* Build the string containing the complete log line. */
        $line = $this->_format($this->_lineFormat,
                               strftime($this->_timeFormat),
                               $priority, $message) . $this->_eol;

		error_log($line, 3,$this->_filename);
echo $line;
    }

    function emerg($message)
    {
        return $this->log($message, PEAR_LOG_EMERG);
    }

    function alert($message)
    {
        return $this->log($message, PEAR_LOG_ALERT);
    }

    function crit($message)
    {
        return $this->log($message, PEAR_LOG_CRIT);
    }

    function err($message)
    {
        return $this->log($message, PEAR_LOG_ERR);
    }

    function warning($message)
    {
        return $this->log($message, PEAR_LOG_WARNING);
    }

    function notice($message)
    {
        return $this->log($message, PEAR_LOG_NOTICE);
    }

    function info($message)
    {
        return $this->log($message, PEAR_LOG_INFO);
    }

    function debug($message)
    {
        return $this->log($message, PEAR_LOG_DEBUG);
    }

    function _extractMessage($message)
    {
        /*
         * If we've been given an object, attempt to extract the message using
         * a known method.  If we can't find such a method, default to the
         * "human-readable" version of the object.
         *
         * We also use the human-readable format for arrays.
         */
        if (is_object($message)) {
            if (method_exists($message, 'getmessage')) {
                $message = $message->getMessage();
            } else if (method_exists($message, 'tostring')) {
                $message = $message->toString();
            } else if (method_exists($message, '__tostring')) {
                $message = (string)$message;
            } else {
                $message = var_export($message, true);
            }
        } else if (is_array($message)) {
            if (isset($message['message'])) {
                if (is_scalar($message['message'])) {
                    $message = $message['message'];
                } else {
                    $message = var_export($message['message'], true);
                }
            } else {
                $message = var_export($message, true);
            }
        } else if (is_bool($message) || $message === NULL) {
            $message = var_export($message, true);
        }

        /* Otherwise, we assume the message is a string. */
        return $message;
    }

    function _format($format, $timestamp, $priority, $message)
    {
        /*
         * If the format string references any of the backtrace-driven
         * variables (%5 %6,%7,%8), generate the backtrace and fetch them.
         */
        if (preg_match('/%[5678]/', $format)) {
            /* Plus 2 to account for our internal function calls. */
            $d = $this->_backtrace_depth + 2;
            list($file, $line, $func, $class) = $this->_getBacktraceVars($d);
        }

        /*
         * Build the formatted string.  We use the sprintf() function's
         * "argument swapping" capability to dynamically select and position
         * the variables which will ultimately appear in the log string.
         */
        return sprintf($format,
                       $timestamp,
                       $this->_ident,
                       $this->priorityToString($priority),
                       $message,
                       isset($file) ? $file : '',
                       isset($line) ? $line : '',
                       isset($func) ? $func : '',
                       isset($class) ? $class : '');
    }

    function priorityToString($priority)
    {
        $levels = array(
            PEAR_LOG_EMERG   => 'emergency',
            PEAR_LOG_ALERT   => 'alert',
            PEAR_LOG_CRIT    => 'critical',
            PEAR_LOG_ERR     => 'error',
            PEAR_LOG_WARNING => 'warning',
            PEAR_LOG_NOTICE  => 'notice',
            PEAR_LOG_INFO    => 'info',
            PEAR_LOG_DEBUG   => 'debug'
        );

        return $levels[$priority];
    }

    function _getBacktraceVars($depth)
    {
        /* Start by generating a backtrace from the current call (here). */
        $bt = debug_backtrace();

        /* Store some handy shortcuts to our previous frames. */
        $bt0 = isset($bt[$depth]) ? $bt[$depth] : null;
        $bt1 = isset($bt[$depth + 1]) ? $bt[$depth + 1] : null;

        /*
         * If we were ultimately invoked by the composite handler, we need to
         * increase our depth one additional level to compensate.
         */
        $class = isset($bt1['class']) ? $bt1['class'] : null;
        if ($class !== null && strcasecmp($class, 'Log_composite') == 0) {
            $depth++;
            $bt0 = isset($bt[$depth]) ? $bt[$depth] : null;
            $bt1 = isset($bt[$depth + 1]) ? $bt[$depth + 1] : null;
            $class = isset($bt1['class']) ? $bt1['class'] : null;
        }

        /*
         * We're interested in the frame which invoked the log() function, so
         * we need to walk back some number of frames into the backtrace.  The
         * $depth parameter tells us where to start looking.   We go one step
         * further back to find the name of the encapsulating function from
         * which log() was called.
         */
        $file = isset($bt0) ? $bt0['file'] : null;
        $line = isset($bt0) ? $bt0['line'] : 0;
        $func = isset($bt1) ? $bt1['function'] : null;

        /*
         * However, if log() was called from one of our "shortcut" functions,
         * we're going to need to go back an additional step.
         */
        if (in_array($func, array('emerg', 'alert', 'crit', 'err', 'warning',
                                  'notice', 'info', 'debug'))) {
            $bt2 = isset($bt[$depth + 2]) ? $bt[$depth + 2] : null;

            $file = is_array($bt1) ? $bt1['file'] : null;
            $line = is_array($bt1) ? $bt1['line'] : 0;
            $func = is_array($bt2) ? $bt2['function'] : null;
            $class = isset($bt2['class']) ? $bt2['class'] : null;
        }

        /*
         * If we couldn't extract a function name (perhaps because we were
         * executed from the "main" context), provide a default value.
         */
        if ($func === null) {
            $func = '(none)';
        }

        /* Return a 4-tuple containing (file, line, function, class). */
        return array($file, $line, $func, $class);
    }

}

php版照片按拍照日期归类整理源码,布布扣,bubuko.com

时间: 2024-10-15 00:45:46

php版照片按拍照日期归类整理源码的相关文章

分享我用Qt开发应用程序【一】,附绿色版下载,以后会慢慢公布源码

写在前面: 1.第一版的代码还有些烂,等功能开发齐全了,做一次重构,再慢慢分享代码 2.邮箱功能.自动升级功能还没有做,笔记功能和备忘功能是好用的,大家如果不嫌弃,可以先用起来 3.笔记功能目前还不能直接贴图或贴附件到编辑器里去,我后续会把这个功能加上去 4.用的是qt5.3+sqlite 3 5.笔记里的编辑器是用webview引入进来的kindeditor,本来打算用百度开源的编辑器,但是一启动就崩溃,联系百度的开发人员都没能解决,后来就放弃尝试了 6.界面中的所有icon图标都是用的fon

iOS 选择的照片或者拍照的图片上添加日期水印

1..引入框架 #import "CLLocation+GPSDictionary.h"#import "NSDictionary+CLLocation.h" #import <AssetsLibrary/AssetsLibrary.h> 2. - (void) imagePickerController: (UIImagePickerController*) reader didFinishPickingMediaWithInfo: (NSDictio

【学习ios之路:UI系列】点击更换头像实现从相册读取照片和拍照两种功能

功能如下: 1.点击头像,提示选择更换头像方式①相册 ②照相. 2.点击相册,实现通过读取系统相册,获取图片进行替换. 3.点击照相,通过摄像头照相,进行替换照片. 4.如果摄像头,弹出框警告. 代码如下: 1.通过UIActionSheet对象实现提示功能 //创建对象 UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle: @"提示" delegate:self cancelButtonTitle:@&q

关于选择照片和拍照

//选择照片 - (IBAction)selectedPhoto:(id)sender { UIImagePickerController *pickVC = [[UIImagePickerController alloc] init]; /* UIImagePickerControllerSourceTypePhotoLibrary, 显示所有文件夹 UIImagePickerControllerSourceTypeCamera,   调用系统摄像头 UIImagePickerControll

IOS10.3上传照片只能拍照不能选择解决办法

升级IOS10.3正式版以后可能会出现上传文件的控件只能拍照而不能选择现有图片的问题. 正好被我们碰到了,于是找了找解决思路,发现如下解决思路: 原代码为: <input type="file" capture accept="image/*"/> 大家可能注意到capture属性了,加这个capture属性当时好像为了解决安卓兼容问题,但ios10.3却认为加了这个属性只允许拍照.因此, 解决办法为:去掉capture属性 修改后的代码如下: <

Android自定义ViewGroup (选择照片或者拍照)

教你搞定Android自定义ViewGroup http://www.jianshu.com/p/138b98095778 字数1794 阅读7030 评论8 喜欢37 上一篇我们介绍了Android中自定义View的知识,并实现了一个类似Google彩虹进度条的自定义View,今天我们将进一步学习如何去自定义一个ViewGroup. ViewGroup 我们知道ViewGroup就是View的容器类,我们经常用的LinearLayout,RelativeLayout等都是ViewGroup的子

微信小程序开发选取相册照片/拍照API调用

作者最近在探索微信小程序,有一个需求是让用户通过手机相册或者手机摄像头拍照上传图片.效果如下图所示: 由于作者之前没有接触过微信小程序,看了微信小程序的开发手册后就开始写了. 一开始的想法是这样的: 通过界面交互反馈的api来显示操作菜单,在操作菜单中如下定义名称,然后再判断执行 在看api文档时,发现貌似可以直接调用图片api 直接使用媒体中的图片api也可以很方便的获取预期效果,代码如下.只是这样微信web开发者工具不显示操作菜单,只有真机才显示操作菜单. 最后,真机效果如下图所示: 原文地

快速归类整型常数——枚举

枚举类型是一种特殊的引用类型,它的声明和使用与类和接口有类似的地方,可以在其它类的内部声明,但不能在方法内部声明. 每个枚举类型都隐含的继承了Enum抽象类,Enum又是Object类的子类,所以其方法即可被枚举类型调用. 1.枚举类型的定义 枚举类型声明使用enum关键字,声明特定的常量,一般用大写字母表示. 1 enum WeekDay 2 { 3 SUNDAY,MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY; 4 } 5 public c

富头像上传编辑器----很好用的上传照片和拍照功能

富头像编辑器是一个很好的头像图片上传控件,能够对图片进行简单的处理,例如:剪切.调节亮度等功能:富头像编辑器拥有很的参数配置,可根据自己的需要配置控件的功能:该控件要求浏览器需安装Flash Player后才能使用:下面是我做的一个小的Demo以说明富头像编辑器的使用方法. 1.前台页面 需引用js文件和初始化富头像编辑器,脚本代码如下: <!DOCTYPE html> <html> <head> <meta charset="utf-8" /