我写了一个图片上传,并且生成缩略图的小程序,本以为就此万事大吉,没想到啊,实际使用中,图片文件一旦超过2M,缩略时内存使用量飙升,真的是飙升啊,一点都不夸张的。2M以内时使用内存才20M以内,大部分虚拟主机都能跑跑,一旦超越2M……比如说,3.5M大约要吃130M内存,5M内存使用量甚至到了290M!!
因为此程序主要是用于大图上传的,而且必须是后台生成缩略图,是冲印网站给普通用户用的。麻烦啊,用了几种缩略类,情况是一摸一样的,内存消耗降不下来。哪位有什么解决办法啊,万分感谢!以下是我的代码:
---class/image.class.php---
<?php
class CreatMiniature
{
//公共变量
var $srcFile=""; //原图
var $echoType; //输出图片类型,link--不保存为文件;file--保存为文件
var $im=""; //临时变量
var $srcW=""; //原图宽
var $srcH=""; //原图高
//设置变量及初始化
function SetVar($srcFile,$echoType)
{
if (!file_exists($srcFile)){
echo '源图片文件不存在!';
exit();
}
$this->srcFile=$srcFile;
$this->echoType=$echoType;
$info = "";
$data = GetImageSize($this->srcFile,$info);
switch ($data[2])
{
case 1:
if(!function_exists("imagecreatefromgif")){
echo "你的GD库不能使用GIF格式的图片,请使用Jpeg或PNG格式!<a href='javascript:go(-1);'>返回</a>";
exit();
}
$this->im = ImageCreateFromGIF($this->srcFile);
break;
case 2:
if(!function_exists("imagecreatefromjpeg")){
echo "你的GD库不能使用jpeg格式的图片,请使用其它格式的图片!<a href='javascript:go(-1);'>返回</a>";
exit();
}
$this->im = ImageCreateFromJpeg($this->srcFile);
break;
case 3:
$this->im = ImageCreateFromPNG($this->srcFile);
break;
}
$this->srcW=ImageSX($this->im);
$this->srcH=ImageSY($this->im);
}
//生成扭曲型缩图
function Distortion($toFile,$toW,$toH)
{
$cImg=$this->CreatImage($this->im,$toW,$toH,0,0,0,0,$this->srcW,$this->srcH);
return $this->EchoImage($cImg,$toFile);
ImageDestroy($cImg);
}
//生成按比例缩放的缩图
function Prorate($toFile,$toW,$toH)
{
$toWH=$toW/$toH;
$srcWH=$this->srcW/$this->srcH;
if($toWH<=$srcWH)
{
$ftoW=$toW;
$ftoH=$ftoW*($this->srcH/$this->srcW);
}
else
{
$ftoH=$toH;
$ftoW=$ftoH*($this->srcW/$this->srcH);
}
if($this->srcW>$toW||$this->srcH>$toH)
{
$cImg=$this->CreatImage($this->im,$ftoW,$ftoH,0,0,0,0,$this->srcW,$this->srcH);
return $this->EchoImage($cImg,$toFile);
ImageDestroy($cImg);
}
else
{
$cImg=$this->CreatImage($this->im,$this->srcW,$this->srcH,0,0,0,0,$this->srcW,$this->srcH);
return $this->EchoImage($cImg,$toFile);
ImageDestroy($cImg);
}
}
//生成最小裁剪后的缩图
function Cut($toFile,$toW,$toH)
{
$toWH=$toW/$toH;
$srcWH=$this->srcW/$this->srcH;
if($toWH<=$srcWH)
{
$ctoH=$toH;
$ctoW=$ctoH*($this->srcW/$this->srcH);
}
else
{
$ctoW=$toW;
$ctoH=$ctoW*($this->srcH/$this->srcW);
}
$allImg=$this->CreatImage($this->im,$ctoW,$ctoH,0,0,0,0,$this->srcW,$this->srcH);
$cImg=$this->CreatImage($allImg,$toW,$toH,0,0,($ctoW-$toW)/2,($ctoH-$toH)/2,$toW,$toH);
return $this->EchoImage($cImg,$toFile);
ImageDestroy($cImg);
ImageDestroy($allImg);
}
//生成背景填充的缩图
function BackFill($toFile,$toW,$toH,$bk1=255,$bk2=255,$bk3=255)
{
$toWH=$toW/$toH;
$srcWH=$this->srcW/$this->srcH;
if($toWH<=$srcWH)
{
$ftoW=$toW;
$ftoH=$ftoW*($this->srcH/$this->srcW);
}
else
{
$ftoH=$toH;
$ftoW=$ftoH*($this->srcW/$this->srcH);
}
if(function_exists("imagecreatetruecolor"))
{
@$cImg=ImageCreateTrueColor($toW,$toH);
if(!$cImg)
{
$cImg=ImageCreate($toW,$toH);
}
}
else
{
$cImg=ImageCreate($toW,$toH);
}
$backcolor = imagecolorallocate($cImg, $bk1, $bk2, $bk3); //填充的背景颜色
ImageFilledRectangle($cImg,0,0,$toW,$toH,$backcolor);
if($this->srcW>$toW||$this->srcH>$toH)
{
$proImg=$this->CreatImage($this->im,$ftoW,$ftoH,0,0,0,0,$this->srcW,$this->srcH);
if($ftoW<$toW)
{
ImageCopy($cImg,$proImg,($toW-$ftoW)/2,0,0,0,$ftoW,$ftoH);
}
else if($ftoH<$toH)
{
ImageCopy($cImg,$proImg,0,($toH-$ftoH)/2,0,0,$ftoW,$ftoH);
}
else
{
ImageCopy($cImg,$proImg,0,0,0,0,$ftoW,$ftoH);
}
}
else
{
ImageCopyMerge($cImg,$this->im,($toW-$ftoW)/2,($toH-$ftoH)/2,0,0,$ftoW,$ftoH,100);
}
return $this->EchoImage($cImg,$toFile);
ImageDestroy($cImg);
}
function CreatImage($img,$creatW,$creatH,$dstX,$dstY,$srcX,$srcY,$srcImgW,$srcImgH)
{
if(function_exists("imagecreatetruecolor"))
{
@$creatImg = ImageCreateTrueColor($creatW,$creatH);
if($creatImg)
ImageCopyResampled($creatImg,$img,$dstX,$dstY,$srcX,$srcY,$creatW,$creatH,$srcImgW,$srcImgH);
else
{
$creatImg=ImageCreate($creatW,$creatH);
ImageCopyResized($creatImg,$img,$dstX,$dstY,$srcX,$srcY,$creatW,$creatH,$srcImgW,$srcImgH);
}
}
else
{
$creatImg=ImageCreate($creatW,$creatH);
ImageCopyResized($creatImg,$img,$dstX,$dstY,$srcX,$srcY,$creatW,$creatH,$srcImgW,$srcImgH);
}
return $creatImg;
}
//输出图片,link---只输出,不保存文件。file--保存为文件
function EchoImage($img,$to_File)
{
switch($this->echoType)
{
case "link":
if(function_exists('imagejpeg')) return ImageJpeg($img);
else return ImagePNG($img);
break;
case "file":
if(function_exists('imagejpeg')) return ImageJpeg($img,$to_File);
else return ImagePNG($img,$to_File);
break;
}
}
}
?>
---class/miniature_memory.php---
<?php
function miniatureMemory($uploadfile){
$imageInfo = getimagesize($uploadfile);
$memoryNeeded = round(($imageInfo[0] * $imageInfo[1] * $imageInfo['bits'] * $imageInfo['channels'] / 8 + Pow(2, 16)) * 1.8);#echo $memoryNeeded;exit;
if (function_exists('memory_get_usage') && memory_get_usage() + $memoryNeeded > (integer) ini_get('memory_limit') * pow(1024, 2))
{
ini_set('memory_limit', (integer) ini_get('memory_limit') + ceil(((memory_get_usage() + $memoryNeeded) - (integer) ini_get('memory_limit') * pow(1024, 2)) / pow(1024, 2)) . 'M');
}
}
?>
因为此程序主要是用于大图上传的,而且必须是后台生成缩略图,是冲印网站给普通用户用的。麻烦啊,用了几种缩略类,情况是一摸一样的,内存消耗降不下来。哪位有什么解决办法啊,万分感谢!以下是我的代码:
---class/image.class.php---
<?php
class CreatMiniature
{
//公共变量
var $srcFile=""; //原图
var $echoType; //输出图片类型,link--不保存为文件;file--保存为文件
var $im=""; //临时变量
var $srcW=""; //原图宽
var $srcH=""; //原图高
//设置变量及初始化
function SetVar($srcFile,$echoType)
{
if (!file_exists($srcFile)){
echo '源图片文件不存在!';
exit();
}
$this->srcFile=$srcFile;
$this->echoType=$echoType;
$info = "";
$data = GetImageSize($this->srcFile,$info);
switch ($data[2])
{
case 1:
if(!function_exists("imagecreatefromgif")){
echo "你的GD库不能使用GIF格式的图片,请使用Jpeg或PNG格式!<a href='javascript:go(-1);'>返回</a>";
exit();
}
$this->im = ImageCreateFromGIF($this->srcFile);
break;
case 2:
if(!function_exists("imagecreatefromjpeg")){
echo "你的GD库不能使用jpeg格式的图片,请使用其它格式的图片!<a href='javascript:go(-1);'>返回</a>";
exit();
}
$this->im = ImageCreateFromJpeg($this->srcFile);
break;
case 3:
$this->im = ImageCreateFromPNG($this->srcFile);
break;
}
$this->srcW=ImageSX($this->im);
$this->srcH=ImageSY($this->im);
}
//生成扭曲型缩图
function Distortion($toFile,$toW,$toH)
{
$cImg=$this->CreatImage($this->im,$toW,$toH,0,0,0,0,$this->srcW,$this->srcH);
return $this->EchoImage($cImg,$toFile);
ImageDestroy($cImg);
}
//生成按比例缩放的缩图
function Prorate($toFile,$toW,$toH)
{
$toWH=$toW/$toH;
$srcWH=$this->srcW/$this->srcH;
if($toWH<=$srcWH)
{
$ftoW=$toW;
$ftoH=$ftoW*($this->srcH/$this->srcW);
}
else
{
$ftoH=$toH;
$ftoW=$ftoH*($this->srcW/$this->srcH);
}
if($this->srcW>$toW||$this->srcH>$toH)
{
$cImg=$this->CreatImage($this->im,$ftoW,$ftoH,0,0,0,0,$this->srcW,$this->srcH);
return $this->EchoImage($cImg,$toFile);
ImageDestroy($cImg);
}
else
{
$cImg=$this->CreatImage($this->im,$this->srcW,$this->srcH,0,0,0,0,$this->srcW,$this->srcH);
return $this->EchoImage($cImg,$toFile);
ImageDestroy($cImg);
}
}
//生成最小裁剪后的缩图
function Cut($toFile,$toW,$toH)
{
$toWH=$toW/$toH;
$srcWH=$this->srcW/$this->srcH;
if($toWH<=$srcWH)
{
$ctoH=$toH;
$ctoW=$ctoH*($this->srcW/$this->srcH);
}
else
{
$ctoW=$toW;
$ctoH=$ctoW*($this->srcH/$this->srcW);
}
$allImg=$this->CreatImage($this->im,$ctoW,$ctoH,0,0,0,0,$this->srcW,$this->srcH);
$cImg=$this->CreatImage($allImg,$toW,$toH,0,0,($ctoW-$toW)/2,($ctoH-$toH)/2,$toW,$toH);
return $this->EchoImage($cImg,$toFile);
ImageDestroy($cImg);
ImageDestroy($allImg);
}
//生成背景填充的缩图
function BackFill($toFile,$toW,$toH,$bk1=255,$bk2=255,$bk3=255)
{
$toWH=$toW/$toH;
$srcWH=$this->srcW/$this->srcH;
if($toWH<=$srcWH)
{
$ftoW=$toW;
$ftoH=$ftoW*($this->srcH/$this->srcW);
}
else
{
$ftoH=$toH;
$ftoW=$ftoH*($this->srcW/$this->srcH);
}
if(function_exists("imagecreatetruecolor"))
{
@$cImg=ImageCreateTrueColor($toW,$toH);
if(!$cImg)
{
$cImg=ImageCreate($toW,$toH);
}
}
else
{
$cImg=ImageCreate($toW,$toH);
}
$backcolor = imagecolorallocate($cImg, $bk1, $bk2, $bk3); //填充的背景颜色
ImageFilledRectangle($cImg,0,0,$toW,$toH,$backcolor);
if($this->srcW>$toW||$this->srcH>$toH)
{
$proImg=$this->CreatImage($this->im,$ftoW,$ftoH,0,0,0,0,$this->srcW,$this->srcH);
if($ftoW<$toW)
{
ImageCopy($cImg,$proImg,($toW-$ftoW)/2,0,0,0,$ftoW,$ftoH);
}
else if($ftoH<$toH)
{
ImageCopy($cImg,$proImg,0,($toH-$ftoH)/2,0,0,$ftoW,$ftoH);
}
else
{
ImageCopy($cImg,$proImg,0,0,0,0,$ftoW,$ftoH);
}
}
else
{
ImageCopyMerge($cImg,$this->im,($toW-$ftoW)/2,($toH-$ftoH)/2,0,0,$ftoW,$ftoH,100);
}
return $this->EchoImage($cImg,$toFile);
ImageDestroy($cImg);
}
function CreatImage($img,$creatW,$creatH,$dstX,$dstY,$srcX,$srcY,$srcImgW,$srcImgH)
{
if(function_exists("imagecreatetruecolor"))
{
@$creatImg = ImageCreateTrueColor($creatW,$creatH);
if($creatImg)
ImageCopyResampled($creatImg,$img,$dstX,$dstY,$srcX,$srcY,$creatW,$creatH,$srcImgW,$srcImgH);
else
{
$creatImg=ImageCreate($creatW,$creatH);
ImageCopyResized($creatImg,$img,$dstX,$dstY,$srcX,$srcY,$creatW,$creatH,$srcImgW,$srcImgH);
}
}
else
{
$creatImg=ImageCreate($creatW,$creatH);
ImageCopyResized($creatImg,$img,$dstX,$dstY,$srcX,$srcY,$creatW,$creatH,$srcImgW,$srcImgH);
}
return $creatImg;
}
//输出图片,link---只输出,不保存文件。file--保存为文件
function EchoImage($img,$to_File)
{
switch($this->echoType)
{
case "link":
if(function_exists('imagejpeg')) return ImageJpeg($img);
else return ImagePNG($img);
break;
case "file":
if(function_exists('imagejpeg')) return ImageJpeg($img,$to_File);
else return ImagePNG($img,$to_File);
break;
}
}
}
?>
---class/miniature_memory.php---
<?php
function miniatureMemory($uploadfile){
$imageInfo = getimagesize($uploadfile);
$memoryNeeded = round(($imageInfo[0] * $imageInfo[1] * $imageInfo['bits'] * $imageInfo['channels'] / 8 + Pow(2, 16)) * 1.8);#echo $memoryNeeded;exit;
if (function_exists('memory_get_usage') && memory_get_usage() + $memoryNeeded > (integer) ini_get('memory_limit') * pow(1024, 2))
{
ini_set('memory_limit', (integer) ini_get('memory_limit') + ceil(((memory_get_usage() + $memoryNeeded) - (integer) ini_get('memory_limit') * pow(1024, 2)) / pow(1024, 2)) . 'M');
}
}
?>
<?php
session_start();
if(strlen($_SESSION['UID'])<10){ //重置订单及图片编号
$_SESSION['UID']=date("YmdHis").(microtime()*1000000);
$_SESSION['UID']=substr($_SESSION['UID'],0,strlen($_SESSION['UID'])-3);
$_SESSION['picNo']=1;
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>无标题文档</title>
<script type="text/javascript">
<!--
function checkForm(theForm)
{
if(theForm.file.value == "")
{
alert ( "请选择需要上传的图片文件" ) ;
theForm.file.focus();
return false;
}else
{
theForm.sbt.value='文件上传中...';
theForm.sbt.disabled=true;
document.getElementById("pic_form").submit();
return true;
}
}
-->
</script>
</head>
<FORM id="pic_form" name="pic_form" action="saveload.php" method="post" enctype="multipart/form-data">
<table width="238" height=100% border="0" cellspacing="0" cellpadding="0"> <tr>
<td bgcolor="#fde1aa">
<input name="file" type="file" size="15" >
<br>
<br></td>
</tr>
<tr>
<td height="23" background="images/left2.jpg"> </td>
</tr>
<tr>
<td align="center" bgcolor="#fde1aa"><br>
<input name="sbt" id="sbt" type=submit value="上传图片" onClick="JavaScript:return checkForm(this.form);" /><br><br></td>
</tr>
<tr>
<td height="1" align="center" background="images/left2.jpg"></td>
</tr>
<tr>
<td align="center" bgcolor="#fde1aa">
<br><br></td>
</tr>
<tr>
<td height="7" align="center" background="images/left3.jpg"></td>
</tr>
</table>
</form>
---saveload.php(后台处理程序)---
<?php
session_start();
header("Pragma: no-cache");
header("Content-Type: text/html; charset=utf-8");
?>
<!--
<table width="100%" border="0">
<tr>
<td colspan="5"><center>
<img src="images/loading.gif">
</center></td>
</tr>
<tr>
<td colspan="5"><center>
文件上传中……
</center></td>
</tr>
</table>
-->
<?php
require_once('class/file_url.class.php');
$uploaddir=$_SERVER['DOCUMENT_ROOT'].dirname(request_uri())."/users_files/$UID/";if(!is_dir($uploaddir))
mkdir ($uploaddir, 0777); //创建用户文件夹
$type=array("jpg","gif","png","bmp"); //设置允许上传文件的类型
$patch="http://".$_SERVER ['HTTP_HOST'].dirname(request_uri()); //程序所在路径
//获取文件后缀名函数
function fileext($filename)
{
return substr(strrchr($filename, '.'), 1);
}
function crname()
{
$name = $_SESSION['UID'].'-'.$_SESSION['picNo'] ;
$_SESSION['picNo']=$_SESSION['picNo']+1;
return $name;
}
$a=strtolower(fileext($_FILES['file']['name']));
//判断文件类型
if(!in_array(strtolower(fileext($_FILES['file']['name'])),$type))
{
$text=implode(",",$type);
echo "<script type=\"text/javascript\">alert(\"您只能上传以下类型文件:$text\");</script>";
echo "<script type =\"text/javascript\">history.go(-1);</script>";
}
//生成目标文件的文件名
else{
$filename=explode(".",$_FILES['file']['name']);
do
{
$filename[0]=crname(); //设置时间文件名
$name=implode(".",$filename);
$uploadfile=$uploaddir.$name;
}
while(file_exists($uploadfile));
#echo $uploadfile;exit;
if (move_uploaded_file($_FILES['file']['tmp_name'],$uploadfile)){
$arr=getimagesize($uploadfile);
$max_px=1600;
if($arr[0]>=$max_px || $arr[1]>=$max_px){ //对大图片生成缩略图
require_once('class/image.class.php');
require_once('class/miniature_memory.php');
miniatureMemory($uploadfile);
$show_pic=new CreatMiniature();
$show_pic->SetVar($uploadfile,'file');
$show_pic->Prorate($uploaddir.'temp'.$name,$max_px,$max_px);
}
}
else echo 'UpDate Error (02)';
}
?>
大家等我好消息吧!
PHP有什么好解决办法了,也请不吝赐教!
phpThumb - 功能很强大,如何强大还是自己去体会吧。
如果在虚拟空间上使用phpThumb的话,要注意内存大小,有时候如果输入图片过大或其他要求过高,会导致服务器返回内存不足的错误,因为虚拟空间对每个客户的内存分配是有限制的。有种不祥的预感~
2m的jpeg大概也就3k*2k左右大,也就18m的样子。就算是gd的bug也不会是因为“将图片解压成位图“这个原因。纯粹在误人子弟。换imagick试。
不过要服务器支持
问题是要服务器支持怎么办??
不是不能装ImageMagick,问题是给他的是虚拟主机,装那玩意BOSS也不会同意的!
可是又答应过客户要提供这么大图片的预览功能,难道看全图?估计要死翘翘了
这是环境配置,没发现什么问题啊,昨晚一怒之下把upload_max_filesize改到了200M!问题依旧,上传2.65M文件成功,上传2.88M文件失败!即使换成了FLASH上传,到了PHP处理部分就过不去了。move_uploaded_file失败。没想到这么一个本以为很简单的问题,会困扰我这么久