<?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. [SQL]SUTFF内置函数的用法

    STUFF 删除指定长度的字符并在指定的起始点插入另一组字符. 语法 STUFF ( character_expression , start , length , character_express ...

  2. Spring MVC 中的基于注解的 Controller【转】

    原文地址:http://my.oschina.net/abian/blog/128028 终于来到了基于注解的 Spring MVC 了.之前我们所讲到的 handler,需要根据 url 并通过 H ...

  3. (easy)LeetCode 232.Implement Queue using Stacks

    Implement the following operations of a queue using stacks. push(x) -- Push element x to the back of ...

  4. 100. Same Tree(Tree)

    /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * Tre ...

  5. css 使用background背景实现border边框效果

    css中,我们一般使用border给html元素设置边框,但也可以使用background背景来模拟css边框效果,本文章向大家介绍css 使用background背景实现border边框效果,需要的 ...

  6. js控制TR的显示隐藏

    在很多现实的场景中,有的文本框我们希望在选择“是”的按钮之后才出现,这就需要js控制TR的隐藏和显示,如何控制,本文为大家揭晓 下文分享的一段代码:选择是的按钮就显示身高和体重的文本框的代码.注意:r ...

  7. PL/SQL常用设置 可看引用位置更清晰直观 引自:http://blog.csdn.net/xiaoqforever/article/details/27695569

    引自:http://blog.csdn.net/xiaoqforever/article/details/27695569 1,登录后默认自动选中My Objects 默认情况下,PLSQL Deve ...

  8. css选择器nth-child()和nth-of-type()的应用

    <style> .table-striped tbody > tr:nth-child(odd) > td, .table-striped tbody > tr:nth- ...

  9. Android 使用NineOldAndroids实现绚丽的ListView左右滑动删除Item效果

    本文出自xiaanming的博客(http://blog.csdn.net/xiaanming/article/details/18311877) 今天还是给大家带来自定义控件的编写,自定义一个Lis ...

  10. 解决VS2008 开发Windows Mobile 项目生成速度慢的问题

    最近用VS2008开发Windows Mobile程序,使用C#..NET Compact Framework,发现项目生成速度比较慢.用VS2008打开项目后,开始一段时间生成速度还能忍受,时间一长 ...