<?php
/**
* The Upload class
* @author Alex Lee <iuyes@qq.com>
* @license http://opensource.org/licenses/BSD-3-Clause New BSD License
* @version svn:$Id: Upload.php 2014-11-2 22:12:32Z iuyes@qq.com $
*/

/**
* @category runtime
* @package Lotusphp\Upload
*/

error_reporting(0); //屏蔽所有错误信息

class LtUpload
{
/** @var LtConfig config handle */
public $configHandle;

/** @var array config */
public $conf;
public $confgroup;
//getimagesize + $_FILES值
public $getData = '';
private $dir_sep = DIRECTORY_SEPARATOR;
private $err = array('fileEmpty'=>'上传的文件为空','fileIllegal'=>'上传文件非法','filePostfixIllegal'=>'上传文件格式非法','fileSizeIllegal'=>'上传文件大小非法','fileFailure'=>'上传文件失败','fileSizeToosmall'=>'图片像素太小','fileLayer'=>'分割文件名宽度超出范围','fileCreateDir'=>'创建目录没有权限');

/**
* construct
*/
public function __construct()
{
if (! $this->configHandle instanceof LtConfig)
{
if (class_exists("LtObjectUtil", false))
{
$this->configHandle = LtObjectUtil::singleton("LtConfig");
}
else
{
$this->configHandle = new LtConfig;
}
}
}

/**
* init
*/
public function init()
{
$this->confgroup = $this->configHandle->get("upload");
if (empty($this->confgroup['default']))
{
//详细配置信息(默认配置)
//默认只允许上传gif、jpeg、png、bmp
$this->confgroup['default']['fileType'] = 'image'; //类型为图片,参数为file则为只上传
$this->confgroup['default']['cutting'] = FALSE; //是否需要切图
$this->confgroup['default']['cutType'] = 1; //切图方式,1:等比缩放,2:
$this->confgroup['default']['cutSize'] = array(array('width'=>0,'height'=>0)); //默认等比例缩微切割宽度
$this->confgroup['default']['allowType'] = array('gif','jpeg','jpg','png'); //可以上传的图片类型
$this->confgroup['default']['checkType'] = TRUE; //是否检查图片格式
$this->confgroup['default']['checkSize'] = TRUE; //是否检查图片大小
$this->confgroup['default']['maxSize'] = 2097152; //上传最大值, 单位字节
$this->confgroup['default']['pathFormat'] ='/upload/image/{yyyy}{mm}/{dd}/{time}{rand:6}';

$this->conf = $this->confgroup['default'];
}
else
{
$this->conf = $this->confgroup['default'];
}
}

public function setUpload($configName)
{
$this->confgroup[$configName]? $this->conf = $this->confgroup[$configName] : $this->conf = $this->confgroup['default'];
}

//文件原图上传
public function put($arr_files = array()) {
$this->getData = & $arr_files;

//判断是否为空
if(!isset($this->getData['tmp_name']) || !isset($this->getData['name']) || empty($this->getData['tmp_name']) || empty($this->getData['name'])) {
$this->halt($this->err['fileEmpty']);
}

//判断是否上传失败
if(isset($this->getData['error']) && $this->getData['error']) {
$this->halt($this->err['fileFailure']);
}

if(is_uploaded_file($this->getData['tmp_name'])) {
$this->checkSafe();
$this->createNewPath();
$this->createDir();

//图片或者文件都可以上传
return $this->doUpload() ? $this->getData : $this->err['fileFailure'];
}
}

/**
* 文件上传开始
*
* @param <string> tmp_name
* @param <string> path, new_path
* @return <boolean>
*/
private function doUpload() {
if(move_uploaded_file($this->getData['tmp_name'], $_SERVER['DOCUMENT_ROOT'].DIRECTORY_SEPARATOR.$this->getData['full_path'])) {
return TRUE;
}
return FALSE;
}

/**
* 判断上传文件大小是否合法
*
* @param <number> size文件大小值
* @return <boolean>
*/
private function checkSize() {
if($this->conf['checkSize'] && $this->getData['size'] > $this->conf['maxSize']) {
return FALSE;
}
return TRUE;
}

/**
* 取得文件名后缀
*
* @param <string> name
* @return <string> 返回后缀名称
*/
private function getPostfix() {
return strtolower(trim(substr(strrchr($this->getData['name'], '.'), 1, 10)));
}

/**
* 检查文件是否为规定上传类型
*
* @param <string> name
* @return <boolean>
*/
private function checkFormat() {
if($this->conf['checkType'] && !in_array($this->getPostfix(), $this->conf['allowType'])) {
return FALSE;
}
return TRUE;
}

/**
* 创建分隔目录
*
* @param <string> path配置目录, new_path完整目录
*/
private function createDir() {
$realpath=$_SERVER['DOCUMENT_ROOT'].DIRECTORY_SEPARATOR.$this->getData['full_path'];
if(!file_exists($path = dirname($realpath))) {
if(!@mkdir($path, 0777, TRUE)) {
return $this->err['fileCreateDir'];
}
}
}

/**
* $autoDir 如果为假, 目录分割功能关闭
*
* @param <string> new_name, new_dir, new_path
* @return <string> new_dir, new_path
*/
private function createNewPath() {

$t = time();
$d = explode('-', date("Y-y-m-d-H-i-s"));
$format = $this->conf["pathFormat"];
$format = str_replace("{yyyy}", $d[0], $format);
$format = str_replace("{yy}", $d[1], $format);
$format = str_replace("{mm}", $d[2], $format);
$format = str_replace("{dd}", $d[3], $format);
$format = str_replace("{hh}", $d[4], $format);
$format = str_replace("{ii}", $d[5], $format);
$format = str_replace("{ss}", $d[6], $format);
$format = str_replace("{time}", $t, $format);

//替换随机字符串
$randNum = rand(1, 10000000000) . rand(1, 10000000000);
if (preg_match("/\{rand\:([\d]*)\}/i", $format, $matches)) {
$format = preg_replace("/\{rand\:[\d]*\}/i", substr($randNum, 0, $matches[1]), $format);
}
$this->getData['full_path']= $format.'.'.$this->getPostfix();
}

/**
* 图片有效性检测
*
* @param <string> fullPath 完整全路径地址
* @return <string> width图片宽度, height图片高度, img_type_number图片数字类型
*/
private function checkSafe() {
if(!$this->checkFormat()) {
$this->halt($this->err['filePostfixIllegal']);
}

if(!$this->checkSize()) {
$this->halt($this->err['fileSizeIllegal']);
}

$this->getImage();
}

/**
* 取得图片的长、宽、类型
*
* @param <string> fullPath 完整全路径地址
*/
private function getImage($fullPath = '') {
if ($this->conf['fileType'] == 'image') {
list($this->getData['width'], $this->getData['height'], $this->getData['img_type_number']) = getimagesize($fullPath ? $fullPath : $this->getData['tmp_name']);
if(!in_array($this->getData['img_type_number'], array(1,2,3))) {
$this->halt($this->err['filePostfixIllegal']);
}
}
}

/**
* 生成等比例缩微图thumb
*
* @return <boolean> TRUE 成功, FALSE 失败
*/
public function putThumb() {
$filePath = $_SERVER['DOCUMENT_ROOT'].DIRECTORY_SEPARATOR.$this->getData['full_path'];

if($filePath && $this->conf['fileType'] == 'image' && $this->conf['cutting'] && @file_exists($filePath)) {

if(!isset($this->getData['width']) || !isset($this->getData['height'])) {
$this->getImage($filePath);
}

if(!in_array($this->getData['img_type_number'], array(1,2,3))) {
return $this->err['filePostfixIllegal'];
}

switch($this->getData['img_type_number']) {
case 1:
$im = imagecreatefromgif($filePath);
break;
case 2:
$im = imagecreatefromjpeg($filePath);
break;
case 3:
$im = imagecreatefrompng($filePath);
break;
}

if(!$im) {
return FALSE;
}

foreach($this->conf['cutSize'] as $img){
$imgWidth=$img['width'];
$imgHeight=$img['height'];
$filename=$img['width'].'-'.$img['height'];

if($img['width'] > $this->getData['width'] && $img['width']>0){$img['width'] = $this->getData['width'];}
if($img['height'] > $this->getData['height'] && $img['height']>0){ $img['height']= $this->getData['height'];}

$width = $img['width'];
$height = $img['height'];

if ($img['width']>0 && ($this->getData['width'] < $this->getData['height'])) {
$width = ($img['height'] / $this->getData['height']) * $this->getData['width'];
} else {
$height = ($img['width'] / $this->getData['width']) * $this->getData['height'];
}

if (function_exists("imagecreatetruecolor")) {

if($this->conf['cutType'] ==1 ){
$new = imagecreatetruecolor($width, $height);

$this->getData['img_type_number'] == 3 && $this->transparent($new);
imagecopyresampled($new, $im, 0, 0, 0, 0, $width, $height, $this->getData['width'], $this->getData['height']);
}else{
$dst_x = 0;
$dst_y = 0;
if ( ($imgWidth/$imgHeight - $width/$height) > 0 ) {
$dst_x = ( $imgWidth - $width ) / 2;
} elseif ( ($imgWidth/$imgHeight - $width/$height) < 0 ) {
$dst_y = ( $imgHeight - $height ) / 2;
}

$new = imagecreatetruecolor($imgWidth, $imgHeight);
$color = imagecolorallocate($new, hexdec(substr($this->conf['bgcolor'], 1, 2)), hexdec(substr($this->conf['bgcolor'], 3, 2)), hexdec(substr($this->conf['bgcolor'], 5, 2)));
imagefill($new, 0, 0, $color);
imagecopyresampled($new, $im, $dst_x, $dst_y, 0, 0, $width, $height, $this->getData['width'], $this->getData['height']);
}

} else {
$new = imagecreate($width, $height);
if($this->conf['cutType'] ==1 ){
$new = imagecreatetruecolor($width, $height);
$this->getData['img_type_number'] == 3 && $this->transparent($new);
imagecopyresampled($new, $im, 0, 0, 0, 0, $width, $height, $this->getData['width'], $this->getData['height']);
}else{
$dst_x = 0;
$dst_y = 0;
if ( ($imgWidth/$imgHeight - $width/$height) > 0 ) {
$dst_x = ( $imgWidth - $width ) / 2;
} elseif ( ($imgWidth/$imgHeight - $width/$height) < 0 ) {
$dst_y = ( $imgHeight - $height ) / 2;
}
$new = imagecreatetruecolor($imgWidth, $imgHeight);
$color = imagecolorallocate($new, hexdec(substr($this->conf['bgcolor'], 1, 2)), hexdec(substr($this->conf['bgcolor'], 3, 2)), hexdec(substr($this->conf['bgcolor'], 5, 2)));
imagefill($new, 0, 0, $color);
imagecopyresampled($new, $im, $dst_x, $dst_y, 0, 0, $width, $height, $this->getData['width'], $this->getData['height']);
}
}

$newFilePath = $_SERVER['DOCUMENT_ROOT'].DIRECTORY_SEPARATOR.$this->getData['full_path']. '.' . $filename;

switch ($this->getData['img_type_number']) {
case 1:
imagegif($new, $newFilePath. '.gif');
break;
case 2:
imagejpeg($new, $newFilePath. '.jpg', 100);
break;
case 3:
imagepng($new, $newFilePath. '.png');
break;
}
unset($filePath,$filename, $newFilePath, $width, $height);

}
imagedestroy($new); imagedestroy($im);
return TRUE;
}

return FALSE;
}

/**
* PNG透明背景图片处理
*
* @param <resource> new 资源
* @param <int> transparent 如果分配失败则返回 FALSE
*/
private function transparent($new) {
$transparent = imagecolorallocatealpha($new , 0 , 0 , 0 , 127);
imagealphablending($new , false);
imagefill($new , 0 , 0 , $transparent);
imagesavealpha($new , true);
}

//格式化错误输出
private function halt($message) {
echo $message;
exit();
}
}

LtUpload上传组件的更多相关文章

  1. 从零开始编写自己的C#框架(23)——上传组件使用说明

    文章导航 1.前言 2.上传组件功能说明 3.数据库结构 4.上传配置管理 5.上传组件所使用到的类 6.上传组件调用方法 7.效果演示 8.小结 1.前言 本系列所使用的是上传组件是大神July开发 ...

  2. JS组件系列——Bootstrap文件上传组件:bootstrap fileinput

    前言:之前的三篇介绍了下bootstrap table的一些常见用法,发现博主对这种扁平化的风格有点着迷了.前两天做一个excel导入的功能,前端使用原始的input type='file'这种标签, ...

  3. 基于MVC4+EasyUI的Web开发框架形成之旅--附件上传组件uploadify的使用

    大概一年前,我还在用Asp.NET开发一些行业管理系统的时候,就曾经使用这个组件作为文件的上传操作,在随笔<Web开发中的文件上传组件uploadify的使用>中可以看到,Asp.NET中 ...

  4. Web Uploader - 功能齐全,完美兼容 IE 的上传组件

    文件上传是网站和 Web 应用程序的常用功能,一直没有一款完美的文件上传组件,因此让很多开发人员碰到头疼的浏览器兼容问题. WebUploader 是由 Baidu FEX 团队开发的一款以 HTML ...

  5. 前端上传组件Plupload使用指南

    我之前写过一篇文章<文件上传利器SWFUpload使用指南>,里面介绍了上传组件SWFUpload的使用方法,但现在随着html5技术的逐渐推广和普及,再去使用以flash为上传手段的SW ...

  6. 使用swfupload上传超过30M文件,使用FLASH上传组件

    原文:使用swfupload上传超过30M文件,使用FLASH上传组件 前一段时间会员的上传组件改用FLASH的swfupload来上传,既能很友好的显示上传进度,又能完全满足大文件的上传. 后来服务 ...

  7. Atitit..文件上传组件选型and最佳实践总结(3)----断点续传控件的实现

    Atitit..文件上传组件选型and最佳实践总结(3)----断点续传控件的实现 1. 实现思路:::元插件,元设置... 1 2. 实现流程downzip,unzip,exec 1 3. Zip  ...

  8. Atitit..文件上传组件选型and最佳实践总结(2)----断点续传

    Atitit..文件上传组件选型and最佳实践总结(2)----断点续传 1. 断点续传的原理 1 2. 如何判断一个插件/控件是否支持断点续传?? 1 3. 常用的组件选型结果::马 1 4. 自定 ...

  9. Extjs3.3 + swfUpload2.2 实现多文件上传组件

    [该上传组件已经停止更新,该上传组件已经在项目中使用.在使用过程中如果发现bug请大家回复此贴.2011-02-27] 主要是为了用swfUpload实现上传,为了新鲜好玩. 理解swfUpload可 ...

随机推荐

  1. 浅谈 Linux 内核开发之网络设备驱动

    转自http://www.ibm.com/developerworks/cn/linux/l-cn-networkdriver/ 网络设备介绍 网络设备是计算机体系结构中必不可少的一部分,处理器如果想 ...

  2. mysql设置定时任务

    –查看时间调度器是否开启 SHOW VARIABLES LIKE 'event_scheduler'; SELECT @@event_scheduler; –开启时间调度器 SET GLOBAL ev ...

  3. (整理)streamWriter、streamReader与FileStream

    今天偶然使用VS代码分析,发现CA2000警告,然后其中一条为streamWriter.streamReader与FileStream相关内容,特查询并记录一下. 引文地址:http://bbs.cs ...

  4. 编码中常用的SQL语法

    蓝色标注的都是比较常见的SQL ====================== 开发中常见的SQL: left join , right join 防止丢弃数据 inner join CASE WHNE ...

  5. dhtmlxGrid分页查询,条件查询实例

    使用jquery的ajax get将页面条件请求到后台,取得数据库数据,分页查询,返回前台grid中. 引入所需文件: <script>window.dhx_globalImgPath = ...

  6. 前端开发 Grunt 之 Connect

    在前端开发过程中,我们需要在开发过程中,将开发中的站点部署到服务器上,然后,在浏览器中查看实际的效果,在 Grunt 环境下,可以直接使用集成在 Grunt 中的 Connect 插件完成站点服务器的 ...

  7. SQL必知必会笔记2

    15. 插入数据 1). 数据插入 INSERT 用来将行插入到数据库表中,插入的方式有几种: (1)插入完整的行: INSERT INTO Customers VALUES( '1000000006 ...

  8. java中高级软件工程师面试总结

    最近去了几家公司面试java中高级工程师,打击挺大的,感觉自己一直以来没有很好的深入学习,对各种知识都是一知半解,但心又太高,想找更高薪的职位,结果面试屡屡碰壁,哎,心情好低落,也是时候静下心来,好好 ...

  9. uLua Unity工作机制

    基于ulua 1.25版本,开启C#类型动态注册. 一.  步骤 注册需要Wrap的C#类型. 在WrapFile.cs类中,使用_GT(typeof(XXX)), 注册需要Wrap的C#类型 注册的 ...

  10. 自定义模板语言之simple_tag和自定义过滤器

    扩展你的模板系统 一般是扩展模板的tag和filter两个功能.可以用来创建你自己的tag和filter功能库. 创建模板库 分为两步: 1. 首先决定由模板库在哪一个注册的app下放置,你可以放在一 ...