【原】flash图片批量上传处理专用php类。

2010年06月26日 星期六 20:00

搬离写了5年的渣度空间,这些都是文章备份。


 

昨天晚上写了个flash上传图片处理类。

1.使用gd库检测接收文件的格式,而非普通的后缀名或MIME格式检查。排除jpeg木马。
2.可设定图片存储的高宽限制。超过限制将强制按原宽高比例缩小到限制大小。
3.启用了相关身份认证。
4.接收图片旋转参数,可旋转原图片。
5.日志记录功能。保存图片错误或成功时都有日志记录。
6.详细的utf-8编码的xml格式相关处理反馈。便于flash操作。
调用:
 
<?php
include_once("YImgUpload.class.php");
$upObject=new YImgUpload();
//如设置$upObject->needIdentity=false;将不进行身份认证,便于在flash中调试
$upObject->needIdentity=false;
$upObject->files=$_FILES; //设置file数组。(只能单张)
$upObject->session=$_POST["session"]; //设置session_id()
//下面是可选参数。
$upObject->params["rotation"]=$_POST["rotation"];
$upObject->params["cookie"]=$_POST["cookie"];
$upObject->params["allowComment"]=$_POST["allowComment"];
$upObject->params["allowReprint"]=$_POST["allowReprint"];
//请记住先检测,再上传
$upObject->check();
$upObject->upload();
?>


文件处理类。名称:YImgUpload.class.php

 
<?php


/*-----------------------------------------------------------------
* 图片上传处理专用封装类。适合配合flash上传使用。
 *@author: yukon12345  http://blog.csdn.net/yukon12345
*默认与flash上传控YUploadImg配合能接受post参数:
*session,(传输而来的session_id()。因为flash上传本身并不能在http头附加session_id来进行认证。)
*rotation,(图片旋转角度)
*cookie(用js获取到的当前浏览器cookie)
*allowComment,allowReprint(存储是否允许评论,允许转帖。现并无特殊用途仅用于日志记录,便于开发时调试)
*默认的$_FILES["Filedata"]flash上传
*-----------------------------------------------------------------------------------------
*/
class YImgUpload {

public $needIdentity = true; //是否进行身份认证
public $session = "noSession"; //需赋值的session_id。
public $files; //需赋值的$files.为$_FILES
public $params; //次要的附加参数
public $upload_name = "Filedata"; //接收上传来的标示名。flash默认"Filedata"
public $max_file_size_in_bytes = 2097152; //上传大小限制默认2M
public $max_size = 2000; //图片最大宽高注意允许的宽高过大会造成服务器资源消耗。并造成执行30秒超时。
public $MAX_FILENAME_LENGTH = 260; //最长文件名
public $extension_whitelist = array (
"jpg",
"gif",
"png",
"jpeg"
); // 允许的后缀
public $upload_contain = "/uploads/"; //上传图片所在文件夹
public $log_path = "logs"; //日志记录的目录。请确认是否有此文件夹
private $save_path; //保存的路径
private $file_name; //原文件名
private $file_extension = "";
private $pic_titler;
private $uploadErrors = array (
0 => "",
1 => "超过最大字节",
2 => "超过最大字节",
3 => "文件不完整",
4 => "无上传文件aaa",
6 => "找不到暂存路径"
);
private $width;
private $height;
public function YImgUpload() {
}
public function check() {

$this->file_name = $this->files[$this->upload_name]['name'];
$this->save_path = dirname(__FILENAME__) . $this->upload_contain;
if ($this->needIdentity == false) {

} else {
session_id($this->session);
session_start();
//下面这一部分可修改成你自己的session检测函数
//注释掉这一段将不会验证发送者的身份
if ($_SESSION["check"] != "yukonTestCode") {

$this->HandleError("身份验证错误");
exit (0);
}
}
//参数设置
date_default_timezone_set('PRC'); //设定时区

//检测gd库
if (function_exists("gd_info")) {
//检测是否开启gd库
$gdinfo = gd_info();
$gdversion = $gdinfo['GD Version']; //获得版本号
preg_match("/([0-9])\.([0-9]+)\.([0-9]+)/", $gdversion, $ver); //获得特定版本号
if ($ver[1] < 2 && $ver[3] < 28) //检查库支持。过低版本不能处理gif
{
$this->HandleError("gd低于2.0.28");
exit (0);
}
} else {
$this->HandleError("没有开启gd库");
exit (0);
}

//检测文件大小和POST数据长度
$POST_MAX_SIZE = ini_get('post_max_size'); //获取php中上传限制参数
$unit = strtoupper(substr($POST_MAX_SIZE, -1)); //获取K,M,G
//获取大小倍数
$multiplier = ($unit == 'M' ? 1048576 : ($unit == 'K' ? 1024 : ($unit == 'G' ? 1073741824 : 1)));
//设定可接收的最大上传字节数。php.ini中限制和你设定的限制中最小的一个。
$max_file_size_in_bytes = $max_file_size_in_bytes > $multiplier * (int) $POST_MAX_SIZE && $POST_MAX_SIZE ? $multiplier * (int) $POST_MAX_SIZE && $POST_MAX_SIZE : $max_file_size_in_bytes;

if ((int) $_SERVER['CONTENT_LENGTH'] > $multiplier * (int) $POST_MAX_SIZE && $POST_MAX_SIZE) {
//header("HTTP/1.1 500 Internal Server Error"); // 触发一个错误
$this->HandleError("文件大小错误");
exit (0);
}

// 初步检查文件
if (!isset ($this->files[$this->upload_name])) {
$this->HandleError("无上传文件");

exit (0);
} else
if (isset ($this->files[$this->upload_name]["error"]) && $this->files[$this->upload_name]["error"] != 0) { //发生错误时
$this->HandleError($this->uploadErrors[$this->files[$this->upload_name]["error"]]);
exit (0);
} else
if (!isset ($this->files[$this->upload_name]["tmp_name"]) || !@ is_uploaded_file($this->files[$this->upload_name]["tmp_name"])) {
$this->HandleError("合法性验证失败");
exit (0);
} else
if (!isset ($this->files[$this->upload_name]['name'])) {
$this->HandleError("无文件名");
exit (0);
}

// 检查php.ini中上传文件大小允许值。
$file_size = @ filesize($this->files[$this->upload_name]["tmp_name"]);
if (!$file_size || $file_size > $this->max_file_size_in_bytes) {
$this->HandleError("文件过大");
exit (0);
}

if ($file_size <= 0) {
$this->HandleError("0字节文件");
exit (0);
}

// 检查文件后缀
$path_info = pathinfo($this->files[$this->upload_name]['name']);
$this->file_extension = strtolower($path_info["extension"]);
$is_valid_extension = false;
$is_valid_extension = in_array($this->file_extension, $this->extension_whitelist); //检查后缀是否在数组中

if (!$is_valid_extension) {
$this->HandleError("文件后缀错误");
exit (0);
}

//如果没有设定旋转就为0度
if (!isset ($params["rotation"])) {
$params["rotation"] = 0;
}

$stamp = time(); //获取时间戳
$pic_title = htmlspecialchars($this->file_name, ENT_QUOTES); //此为可存入数据库的图片标题。需注意防止各种xss攻击和SQL注入。此处仅做特殊字符<>""&编码处理。
$pic_titler = $this->file_name; //此为返回给flash的文件名,用于上传完毕的修改提示
//文件实际在服务器的名字.结合原文件名+暂存名+上传时间的MD5值。
$this->file_name = md5($this->file_name . $stamp . $this->files[$this->upload_name]["tmp_name"]) . "." . $this->file_extension;
//检查同名文件
if (file_exists($this->save_path . $this->file_name)) {
$this->HandleError("已有同名文件");
exit (0);
}

}

/*-----------------------
* 检测上传文件的图片编码,并保存。
* ---------------------------
* */

public function upload() {

//用gd库检查图片的实际编码,并执行相关操作。
if ($isjpeg = @ imagecreatefromjpeg($this->files[$this->upload_name]["tmp_name"])) { //如果是jpeg
获取原图片大小
$this->width = imagesx($isjpeg);
$this->height = imagesy($isjpeg);
if ($this->width > $this->max_size || $this->height > $this->max_size || $this->params["rotation"] != 0) {
//图片大小超过或者需要旋转,启用gd库特别操作
$new_img = $this->resize_image($isjpeg, $this->params["rotation"]);

if (@ imagejpeg($new_img, $this->save_path . $this->file_name)) {
$this->HandleOk("文件保存成功", $this->save_path . $this->file_name, $this->pic_titler);
} else {
$this->HandleError("无法保存");
exit (0);
}
}//gd库特别操作end
else{//图片不超过大小宽高并且无旋转,直接保存
if (@ move_uploaded_file($this->files[$this->upload_name]["tmp_name"], $this->save_path . $this->file_name)) {
$this->HandleOk("文件保存成功", $this->save_path . $this->file_name, $this->pic_titler);
} else {
$this->HandleError("无法保存");
exit (0);
}
}//直接保存end
} //jpeg完
else
if ($ispng = @ imagecreatefrompng($this->files[$this->upload_name]["tmp_name"])) { //如果是png
//变成合适大小并旋转
获取原图片大小
$this->width = imagesx($ispng);
$this->height = imagesy($ispng);
if ($this->width > $this->max_size || $this->height > $this->max_size || $this->params["rotation"] != 0) {
//图片大小超过或者需要旋转,启用gd库特别操作
$new_img = $this->resize_image($ispng, $this->params["rotation"]);

if (@ imagepng($new_img, $this->save_path . $this->file_name)) {
$this->HandleOk("文件保存成功", $this->save_path . $this->file_name, $this->pic_titler);
} else {
$this->HandleError("无法保存");
exit (0);
}
}//gd库特别操作end
else{//图片不超过大小宽高并且无旋转,直接保存
if (@ move_uploaded_file($this->files[$this->upload_name]["tmp_name"], $this->save_path . $this->file_name)) {
$this->HandleOk("文件保存成功", $this->save_path . $this->file_name, $this->pic_titler);
} else {
$this->HandleError("无法保存");
exit (0);
}
}//直接保存end
} //png完
else
if ($isgif = @ imagecreatefromgif($this->files[$this->upload_name]["tmp_name"])) {
//如果是gif,由于使用imagegif将只保留一帧图片,因此使用普通文件保存方法。

if (@ move_uploaded_file($this->files[$this->upload_name]["tmp_name"], $this->save_path . $this->file_name)) {
$this->HandleOk("文件保存成功", $this->save_path . $this->file_name, $this->pic_titler);
} else {
$this->HandleError("无法保存");
exit (0);
}

} //gif完
else {
$this->HandleError("图过大或编码错");
exit (0);
}

exit (0);
}
/*------------------------------------------------
* 调整图片大小。宽高大于设定的变小,并旋转图片
* resize_image("文件资源句柄","旋转度")
*
* @param string $source接收待处理的文件资源句柄
* @param int $rotation旋转多少度
* @return handler $new_img返回处理后的文件资源句柄
* -----------------------------------------
* */
private function resize_image($source, $rotation) {
//获取原图片大小
$max = $this->max_size;
if ($this->width < $max && $this->height < $max) {

//宽高都不超过就只做旋转修改
if ($rotation != 0) { //角度为0直接返回
$new_img = imagerotate($source, $rotation, 0);
} else {
$new_img = $source;
}
return $new_img;
} else { //有超过的边
if ($this->width > $max && $this->height > $max) { //都超过时
if ($this->width >= $this->height) { //宽大于高
$new_width = $max; //宽为max
$new_height = $max / ($this->width / $this->height); //保持宽高比
} else {
$new_height = $max;
$new_width = $max / ($this->height / $this->width);
}
} else
if ($this->width > $max) { //只有宽超过
$new_width = $max;
$new_height = $this->height / ($this->width / $max);
} else
if ($this->height > $max) { //只有高超过
$new_height = $max;
$new_width = $this->width / ($this->height / $max);
}
$dest = imagecreatetruecolor($new_width, $new_height);
//调整图片大小。将原图片填充到目的图片上
imagecopyresized($dest, $source, 0, 0, 0, 0, $new_width, $new_height, $this->width, $this->height);
if ($rotation != 0) {
$new_img = imagerotate($dest, $rotation, 0);
} else {
$new_img = $dest;
}
return $new_img;
}
}

/*---------------------------------
* 上传失败后的操作。用于输出xml,并记录相关参数
* 接收参数:
* @param string $message输出给flash的文字提示
* ----------------------------------
* */

private function HandleError($message) { //发生错误时的日志记录。
$xml = "<?xml version='1.0' encoding='utf-8'?>";
$xml .= "<root><information errorId='1' message='" . $message . "'/></root>";
echo $xml;
//下面为日志记录
$log = date("[H:i:s]");
$log .= "【错误消息:】" . $message;
$log .= "【IP:】" . $this->getIP();
$log .= "【用户名:】" . $this->getUser();
$log .= "【Session:】" . $this->session;
$log .= "【文件名:】" . $this->files[$this->upload_name]['name'];
$log .= "【图片字节数:】" . $this->files[$this->upload_name]['size'];
//$log .= "【Cookie:】" . $this->params['cookie'] ;
$log .= "【AllowComment:】" . $this->params['allowComment'];
$log .= "【AllowReprint:】" . $this->params['allowReprint'];
$log .= "【Rotaion:】" . $this->params['rotation'] . "\r\n";
//日志默认目录:logs 请确定是否有这个目录
@ error_log($log, 3, "./" . $this->log_path . "/errorlog" . date("[Y-m-d]") . ".log");

}

/*---------------------------------
* 上传完毕后的操作。用于输出xml,并记录上传参数
* 接收参数:
* @param string $message输出给flash的文字提示
* @param string $imgURL图片在服务器的相对地址。
* @param string $title图片原名称。
* ----------------------------------
* */

private function HandleOk($message, $imgURL, $title) { //上传成功时的记录
$xml = "<?xml version='1.0' encoding='utf-8'?>";
$xml .= "<root><information errorId='0' message='" . $message . "'url='" . $imgURL . "' title='" . $this->files[$this->upload_name]['name'] . "' /></root>";
echo $xml;
//下面为日志记录
$log = date("[H:i:s]");
$log .= "【IP:】" . $this->getIP();
$log .= "【用户名:】" . $this->getUser();
$log .= "【Session:】" . $this->session;
//$log .= "【Cookie:】" . $this->params['cookie'] ;
$log .= "【图片字节数:】" . $this->files[$this->upload_name]['size'];
$log .= "【原图片宽高:】" . $this->width . "*" . $this->height;
$log .= "【AllowComment:】" . $this->params['allowComment'];
$log .= "【AllowReprint:】" . $this->params['allowReprint'];
$log .= "【Rotaion:】" . $pthis->arams['rotation'] . "\r\n";
error_log($log, 3, "./" . $this->log_path . "/oklog" . date("[Y-m-d]") . ".log");
}
/*----------------------------------
* 返回访问者的IP
* @return IP
* ---------------------------
* */
private function getIP() { //获取上传者IP
if (getenv("HTTP_CLIENT_IP") && strcasecmp(getenv("HTTP_CLIENT_IP"), "unknown")) {
$ip = getenv("HTTP_CLIENT_IP");
} else
if (getenv("HTTP_X_FORWARDED_FOR") && strcasecmp(getenv("HTTP_X_FORWARDED_FOR"), "unknown")) {
$ip = getenv("HTTP_X_FORWARDED_FOR");
} else
if (getenv("REMOTE_ADDR") && strcasecmp(getenv("REMOTE_ADDR"), "unknown")) {
$ip = getenv("REMOTE_ADDR");
} else
if (isset ($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], "unknown")) {
$ip = $_SERVER['REMOTE_ADDR'];
} else {
$ip = "unknown";
}
return ($ip);
}

private function getUser() {
//这里添加获取上传者的网站登陆ID
}

} //class
?>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值