使用404被动生成缩略图

来源:互联网 发布:mac系统游戏 编辑:程序博客网 时间:2024/05/19 17:24

在我们的项目中,图片是根据模板的不同显示不同的规格,所以无法预先生成缩略图。而图片是存储在专门的图片文件服务器上的,我们要求图片请求除第一次生成之外,访问的是真实的图片文件。主要思路是通过404跳转生成缩略图。具体方法:

1. 图片上传到文件服务器,图片的相对路径保存到相应的数据字段中。


2.模板显示的时候,根据模板要求,生成该图片缩略图的URL,缩略图URL中包含有图片原始地址,缩略图大小,缩略规则,水印规则

/** * 根据原图名获取缩略图的访问地址,规格段需要进行加密 * * @param String $filename 文件名 * @param int $width 宽度 * @param int $height 高度 * @param Char $tyep f:fix,fw:fix width,fh:fix height,c:cut,a:auto,n:原图,不做任何处理,图片生成方式 * @param $watermark 水印规则,0表示不加水印 * @param String $toJpeg 是否转换为jpg y:转换 n:不转换 * @return String 缩略图访问地址 */public static function getImgUrl($filename,$width=0,$height=0,$type='f',$watermark=0,$toJpeg='n'){//如果是远程路径,直接返回if(strpos($filename,"http://") === 0){return $filename;}$base_img_url = IMG_BASE_URL;if($filename == ""){return DEFAULT_IMG_URL;}if($type == 'n'){return $base_img_url.$filename;}$extend = pathinfo($filename);$ext    = strtolower($extend["extension"]);//是否转换为jpgif(($ext == 'png') && ($toJpeg == 'y')){$format = 'jpg';}else{$format = $ext;}//$url = str_replace("images",$base_img_url,$filename);$url = $base_img_url.$filename;$width = intval($width);$height = intval($height);if($watermark===0){return str_replace(".$ext",'_'.$ext.'_cacheimages'.'_H_'.Util::encrypt_unrand($width.'_'.$height."_$type").".".$format,$url);}else{return str_replace(".$ext",'_'.$ext.'_cacheimages'.'_H_'.Util::encrypt_unrand($width.'_'.$height."_$type"."_".$watermark).".".$format,$url);}}

3.浏览器向图片服务器请求缩略图的URL,该URL 对应的图片如果已经生成则正常访问

4.如果该图片不存在,则触发404跳转,跳转到我们设定的缩略图生成文件。这一步需要在web服务中设置,将默认的404文件 改成我们的缩略图生成文件,我的是Apache,

<VirtualHost *>serverName img.xxx.comHeader set Access-Control-Allow-Origin http://www.xxx.comDocumentRoot D:/www/xxx/trunk/static/<Directory "D:/www/xxx/trunk/static/">    Options Indexes FollowSymLinks MultiViews    AllowOverride All    Order allow,deny    Allow from all</Directory><span style="background-color: rgb(255, 255, 153);">ErrorDocument 404 /imageServer/404.php</span></VirtualHost>

5.缩略图生成文件时,先解析URL,得出缩略图的原图和各种规则,然后生成,并保存到URL所指定的地址,然后直接输出缩略图数据,显示在浏览器中。

/** * 404错误页面处理图片缩略图生成 */include "config.php";$imgpath = $_SERVER['REDIRECT_URL'] ? $_SERVER['REDIRECT_URL'] : $_SERVER['REQUEST_URI'];$imgpath = substr($imgpath,1,strlen($imgpath)-1);$pos = strpos($imgpath,'?');if($pos !== false){$imgpath = substr($imgpath,0,$pos);}$imgarr = pathinfo($imgpath);if(!in_array(trim(strtolower($imgarr['extension'])),array('jpg','jpeg','gif','png','bmp'))){exit;}$filename = $imgarr['filename'];$arr = explode("_",$filename);$arr_len = count($arr);/** 加密后,解密 **/$spec = explode("_",decrypt2($arr[$arr_len-1]));$w = $spec[0];$h = $spec[1];if($arr[$arr_len-2] != 'H'){$w = ceil($w/2);$h = ceil($h/2);}$spec['2'] = trim($spec['2']);$type = in_array($spec['2'],array('a','f','fw','fh','c','tc','cc')) ? $spec['2'] : 'a';$watermark = isset($spec['3']) ? $spec['3'] : 0;include "imageResize.func.php";//获取原图路径$arr1 = explode("_cacheimages_",$filename);$src_name = $arr1[0];if($arr_len == 6){$file = IMG_DIR.$imgarr['dirname'].'/'.$arr[0].'_'.$arr[1].'.'.$arr[$arr_len-4];}else{$arr2 = explode("_",$src_name);$arr2_len = count($arr2);if($arr2_len == 1){$file = IMG_DIR.$imgarr['dirname'].'/'.$arr2[0].".".$imgarr['extension'];}else{$ex = strtolower ($arr2[$arr2_len-1]);if($ex == 'png' || $ex == 'jpg' || $ex == 'gif' || $ex == 'bmp'){$file = IMG_DIR.$imgarr['dirname'].'/'.$arr2[0].".".$ex;}else{$file = IMG_DIR.$imgarr['dirname'].'/'.$arr2[0].'_'.$arr2[1].".".$imgarr['extension'];}}}//获取缩略图文件名//$imgpath = str_replace('.'.$imgarr['extension'],'.'.$arr[$arr_len-3],$imgpath);$newfile = IMG_DIR.$imgpath;if(imageResize($file,$newfile,$w,$h,$type)){ob_clean();<span style="color:#ffffff;"></span><span style="background-color: rgb(255, 255, 153);">header("HTTP/1.1 200 OK");</span><span style="color:#ffffff;"></span>header("Expires: ".gmdate("D, d M Y H:i:s", time()+315360000)." GMT");header("Cache-Control: max-age=315360000");header("Content-type: image/jpeg");if($watermark==1){imageWaterMark($newfile,9,'../images/watermark150.png');}elseif($watermark==2){imageWaterMark($newfile,9,'../images/watermark200.png');}elseif($watermark==3){imageWaterMark($newfile,9,'../images/watermark250.png');}echo file_get_contents($newfile);}else{ob_clean();<span style="background-color: rgb(255, 255, 153);">header("HTTP/1.1 200 OK");</span>header("Expires: ".gmdate("D, d M Y H:i:s", time()+315360000)." GMT");header("Cache-Control: max-age=315360000");header("Content-type: image/jpeg");$newfile = IMG_DIR."images/default.png";echo file_get_contents($newfile);}function realImage($url,$key = "imgkey"){    //本地要去除项目目录(autowebsite3g_svn)    $url = parse_url($url,PHP_URL_PATH);    if (substr($url, 0, 14) != "/_cache_images") {        return false;    } else {        $url = substr($url, 15);    }        $h = substr($url,0,2);    $url = substr($url,2);    $extend = pathinfo($url);    if($h=='H0'){    $real_url = Util::decrypt($extend['filename'],$key);    $real_url_info = pathinfo($real_url);    $file_info = explode('_', $real_url_info['filename']);    $widthandheight_info = explode('x', $file_info[count($file_info)-2]);    $new_widthandheight = strval(intval($widthandheight_info[0])/2)."x".strval(intval($widthandheight_info[1])/2);    return str_replace($file_info[count($file_info)-2],$new_widthandheight,$real_url);    }else{    return decrypt($extend['filename'],$key);    }}        function decrypt2($txt, $key = 'anihc ctI') {    if($key == 'ewebsoft'){    return $txt;    }    $txt = str_replace("@","_",$txt);        $chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.";        $ikey = "-x6g6ZWm2G9g_vr0Bo.pOq3kRIxsZ6rm";        $knum = 0;        $i = 0;        $tlen = strlen($txt);        while (isset($key{$i}))            $knum +=ord($key{$i++});        $ch1 = $txt{$knum % $tlen};        $nh1 = strpos($chars, $ch1);        $txt = substr_replace($txt, '', $knum % $tlen--, 1);        if(strlen($txt)==0){        //TODO错误处理        echo '非法参数';exit;        }        $ch2 = $txt{$nh1 % $tlen};        $nh2 = strpos($chars, $ch2);        $txt = substr_replace($txt, '', $nh1 % $tlen--, 1);    if(strlen($txt)==0){    //TODO错误处理        echo '非法参数';exit;        }        $ch3 = $txt{$nh2 % $tlen};        $nh3 = strpos($chars, $ch3);        $txt = substr_replace($txt, '', $nh2 % $tlen--, 1);        $nhnum = $nh1 + $nh2 + $nh3;        $mdKey = substr(md5(md5(md5($key . $ch1) . $ch2 . $ikey) . $ch3), $nhnum % 8, $knum % 8 + 16);        $tmp = '';        $j = 0;        $k = 0;        $tlen = strlen($txt);        $klen = strlen($mdKey);        for ($i = 0; $i < $tlen; $i++) {            $k = $k == $klen ? 0 : $k;            $j = strpos($chars, $txt{$i}) - $nhnum - ord($mdKey{$k++});            while ($j < 0)                $j+=64;            $tmp .= $chars{$j};        }        $tmp = str_replace(array('-', '#', '.','@'),array('+', '/', '=','_'),  $tmp);        return base64_decode($tmp);    }             /** 功能:PHP图片水印 (水印支持图片或文字)* 参数:*$groundImage 背景图片,即需要加水印的图片,暂只支持GIF,JPG,PNG格式;*$waterPos水印位置,有10种状态,0为随机位置;*1为顶端居左,2为顶端居中,3为顶端居右;*4为中部居左,5为中部居中,6为中部居右;*7为底端居左,8为底端居中,9为底端居右;*$waterImage图片水印,即作为水印的图片,暂只支持GIF,JPG,PNG格式;*$waterText文字水印,即把文字作为为水印,支持ASCII码,不支持中文;*$textFont文字大小,值为1、2、3、4或5,默认为5;*$textColor文字颜色,值为十六进制颜色值,默认为#FF0000(红色);** 注意:Support GD 2.0,Support FreeType、GIF Read、GIF Create、JPG 、PNG*$waterImage 和 $waterText 最好不要同时使用,选其中之一即可,优先使用 $waterImage。*当$waterImage有效时,参数$waterString、$stringFont、$stringColor均不生效。*加水印后的图片的文件名和 $groundImage 一样。* 作者:longware @ 2004-11-3 14:15:13*/function imageWaterMark($groundImage,$waterPos=0,$waterImage="",$waterText="",$textFont=5,$textColor="#FF0000"){    $isWaterImage = FALSE;    $formatMsg = "暂不支持该文件格式,请用图片处理软件将图片转换为GIF、JPG、PNG格式。";    //读取水印文件    if(!empty($waterImage) && file_exists($waterImage)){        $isWaterImage = TRUE;        $water_info = getimagesize($waterImage);        $water_w = $water_info[0];//取得水印图片的宽        $water_h = $water_info[1];//取得水印图片的高         switch($water_info[2]){//取得水印图片的格式            case 1:$water_im = imagecreatefromgif($waterImage);break;            case 2:$water_im = imagecreatefromjpeg($waterImage);break;            case 3:$water_im = imagecreatefrompng($waterImage);break;            default:die($formatMsg);        }    }    //读取背景图片    if(!empty($groundImage) && file_exists($groundImage)){        $ground_info = getimagesize($groundImage);        $ground_w = $ground_info[0];//取得背景图片的宽        $ground_h = $ground_info[1];//取得背景图片的高        switch($ground_info[2])//取得背景图片的格式        {            case 1:$ground_im = imagecreatefromgif($groundImage);break;            case 2:$ground_im = imagecreatefromjpeg($groundImage);break;            case 3:$ground_im = imagecreatefrompng($groundImage);break;            default:die($formatMsg);        }    }else{        die("需要加水印的图片不存在!");    }    //水印位置    if($isWaterImage)//图片水印    {        $w = $water_w;        $h = $water_h;        $label = "图片的";    }else{//文字水印        $temp = imagettfbbox(ceil($textFont*5),0,"./cour.ttf",$waterText);//取得使用 TrueType 字体的文本的范围        $w = $temp[2] - $temp[6];        $h = $temp[3] - $temp[7];        unset($temp);        $label = "文字区域";    }    if( ($ground_w<$w) || ($ground_h<$h) ){        echo "需要加水印的图片的长度或宽度比水印".$label."还小,无法生成水印!";        return;    }    switch($waterPos){        case 0://随机            $posX = rand(0,($ground_w - $w));            $posY = rand(0,($ground_h - $h));            break;        case 1://1为顶端居左            $posX = 0;            $posY = 0;            break;        case 2://2为顶端居中            $posX = ($ground_w - $w) / 2;            $posY = 0;            break;        case 3://3为顶端居右            $posX = $ground_w - $w;            $posY = 0;            break;        case 4://4为中部居左            $posX = 0;            $posY = ($ground_h - $h) / 2;            break;        case 5://5为中部居中            $posX = ($ground_w - $w) / 2;            $posY = ($ground_h - $h) / 2;            break;        case 6://6为中部居右            $posX = $ground_w - $w;            $posY = ($ground_h - $h) / 2;            break;        case 7://7为底端居左            $posX = 0;            $posY = $ground_h - $h;            break;        case 8://8为底端居中            $posX = ($ground_w - $w) / 2;            $posY = $ground_h - $h;            break;        case 9://9为底端居右            $posX = $ground_w - $w - 10;   // -10 是距离右侧10px 可以自己调节            $posY = $ground_h - $h - 0;   // -10 是距离底部10px 可以自己调节            break;        default://随机            $posX = rand(0,($ground_w - $w));            $posY = rand(0,($ground_h - $h));            break;    }    //设定图像的混色模式    imagealphablending($ground_im, true);    if($isWaterImage){//图片水印        imagecopy($ground_im, $water_im, $posX, $posY, 0, 0, $water_w,$water_h);//拷贝水印到目标文件     }else{//文字水印        if( !emptyempty($textColor) && (strlen($textColor)==7) ){            $R = hexdec(substr($textColor,1,2));            $G = hexdec(substr($textColor,3,2));            $B = hexdec(substr($textColor,5));        }else{            die("水印文字颜色格式不正确!");        }        imagestring ( $ground_im, $textFont, $posX, $posY, $waterText, imagecolorallocate($ground_im, $R, $G, $B));     }    //生成水印后的图片    @unlink($groundImage);    switch($ground_info[2]){//取得背景图片的格式        case 1:imagegif($ground_im,$groundImage);break;        case 2:imagejpeg($ground_im,$groundImage);break;        case 3:imagepng($ground_im,$groundImage);break;        default:die($errorMsg);    }    //释放内存    if(isset($water_info)) unset($water_info);    if(isset($water_im)) imagedestroy($water_im);    unset($ground_info);    imagedestroy($ground_im);}    
注意上面高亮的部分,这是将返回状态从404改回到200。否则在第一次生成的时候,浏览器发现状态是404就不显示图片了。

0 0
原创粉丝点击