gpt4 book ai didi

PHP 缩略图图像生成器缓存 : How to set If-Last-Modified/Max-Age/Last-Modified HEADERS correctly in PHP?

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:58:23 32 4
gpt4 key购买 nike

即使在 Google PageSpeed(97) 和 Yahoo! YSlow(92) PHP 生成的缩略图似乎并不是被动地从旧缓存中获取的:它们似乎每次都生成......又一次......新鲜出炉,消耗大量腰部时间。

这个问题将只关注如何解决生成拇指的PHP代码的CACHE问题:

看看这些每个只有 3 ~ 5 kb 的微小缩略图!

Waterfall in detail: http://www.webpagetest.org/result/110328_AM_8T00/1/details/

任何和所有的建议都是对我的 +1 帮助并热烈欢迎,因为在过去的几个月里我对这个问题变得非常绝望。万分感谢!

是否使用Modrewrite 不影响速度:两者是一样的。我使用这些重写条件:RewriteCond %{REQUEST_URI} ^/IMG-.*$ & RewriteCond %{REQUEST_FILENAME} !-f

original default URLbeautified rewritten URL 都会产生相同的延迟!!因此,让我们不要将错误归咎于闪电般快速的 Apache:它的 PHP 缓存/ header 以某种方式错误编码...

enter image description here


来自 webpagetest.org 的警告:利用静态 Assets 的浏览器缓存:69/100

失败 - (没有最大年龄或过期):http://aster.nu/imgcpu?src=aster_bg/124.jpg&w=1400&h=100&c=p


每次刷新后,你会看到其中一个two warnings appear on random at REDbot.org enter image description here enter image description here


准则的相关部分:

// Script is directly called
if(isset($_GET['src']) && (isset($_GET['w']) || isset($_GET['h']) || isset($_GET['m']) || isset($_GET['f']) || isset($_GET['q']))){
$ImageProcessor = new ImageProcessor(true);
$ImageProcessor->Load($_GET['src'], true);
$ImageProcessor->EnableCache("/var/www/vhosts/blabla.org/httpdocs/tmp/", 345600);
$ImageProcessor->Parse($quality);
}

/* Images processing class
* - create image thumbnails on the fly
* - Can be used with direct url imgcpu.php?src=
* - Cache images for efficiency
*/
class ImageProcessor
{
private $_image_path; # Origninal image path
protected $_image_name; # Image name string
private $_image_type; # Image type int
protected $_mime; # Image mime type string
private $_direct_call = false; # Is it a direct url call? boolean
private $_image_resource; # Image resource var Resource
private $_cache_folder; # Cache folder strig
private $_cache_ttl; # Cache time to live int
private $_cache = false; # Cache on boolean
private $_cache_skip = false; # Cache skip var boolean

private function cleanUrl($image){ # Cleanup url
$cimage = str_replace("\\", "/", $image);
return $cimage;
}

/** Get image resource
* @access private, @param string $image, @param string $extension, @return resource */
private function GetImageResource($image, $extension){
switch($extension){
case "jpg":
@ini_set('gd.jpeg_ignore_warning', 1);
$resource = imagecreatefromjpeg($image);
break;
}
return $resource;
}


/* Save image to cache folder
* @access private, @return void */
private function cacheImage($name, $content){

# Write content file
$path = $this->_cache_folder . $name;
$fh = fopen($path, 'w') or die("can't open file");
fwrite($fh, $content);
fclose($fh);

# Delete expired images
foreach (glob($this->_cache_folder . "*") as $filename) {
if(filemtime($filename) < (time() - $this->_cache_ttl)){
unlink( $filename );
}
}
}

/* Get an image from cache
* @access public, @param string $name, @return void */
private function cachedImage($name){
$file = $this->_cache_folder . $name;
$fh = fopen($file, 'r');
$content = fread($fh, filesize($file));
fclose($fh);
return $content;
}

/* Get name of the cache file
* @access private, @return string */
private function generateCacheName(){
$get = implode("-", $_GET);
return md5($this->_resize_mode . $this->_image_path . $this->_old_width . $this->_old_height . $this->_new_width . $this->_new_height . $get) . "." . $this->_extension;
}

/* Check if a cache file is expired
* @access private, @return bool */
private function cacheExpired(){
$path = $this->_cache_folder . $this->generateCacheName();
if(file_exists($path)){
$filetime = filemtime($path);
return $filetime < (time() - $this->_cache_ttl);
}else{
return true;
}
}

/* Lazy load the image resource needed for the caching to work
* @return void */
private function lazyLoad(){
if(empty($this->_image_resource)){
if($this->_cache && !$this->cacheExpired()){
$this->_cache_skip = true;
return;
}
$resource = $this->GetImageResource($this->_image_path, $this->_extension);
$this->_image_resource = $resource;
}
}

/* Constructor
* @access public, @param bool $direct_call, @return void */
public function __construct($direct_call=false){

# Check if GD extension is loaded
if (!extension_loaded('gd') && !extension_loaded('gd2')) {
$this->showError("GD is not loaded");
}

$this->_direct_call = $direct_call;
}

/* Resize
* @param int $width, @param int $height, @param define $mode
* @param bool $auto_orientation houd rekening met orientatie wanneer er een resize gebeurt */
public function Resize($width=100, $height=100, $mode=RESIZE_STRETCH, $auto_orientation=false){

// Validate resize mode
$valid_modes = array("f", "p");
}
// .... omitted .....

// Set news size vars because these are used for the
// cache name generation
// .... omitted .....
$this->_old_width = $width;
$this->_old_height = $height;

// Lazy load for the directurl cache to work
$this->lazyLoad();
if($this->_cache_skip) return true;

// Create canvas for the new image
$new_image = imagecreatetruecolor($width, $height);

imagecopyresampled($new_image, $this->_image_resource, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h);

// .... omitted .....

$this->_image_resource = $new_image;
}

/* Create image resource from path or url
* @access public, @param string $location, @param bool $lazy_load, @return */
public function Load($image,$lazy_load=false){

// Cleanup image url
$image = $this->cleanUrl($image);

// Check if it is a valid image
if(isset($mimes[$extension]) && ((!strstr($image, "http://") && file_exists($image)) || strstr($image, "http://")) ){

// Urlencode if http
if(strstr($image, "http://")){
$image = str_replace(array('http%3A%2F%2F', '%2F'), array('http://', '/'), urlencode($image));
}
$image = str_replace("+", "%20", $image);

$this->_extension = $extension;
$this->_mime = $mimes[$extension];
$this->_image_path = $image;
$parts = explode("/", $image);
$this->_image_name = str_replace("." . $this->_extension, "", end($parts));

// Get image size
list($width, $height, $type) = getimagesize($image);
$this->_old_width = $width;
$this->_old_height = $height;
$this->_image_type = $type;
}else{
$this->showError("Wrong image type or file does not exists.");
}
if(!$lazy_load){
$resource = $this->GetImageResource($image, $extension);
$this->_image_resource = $resource;
}
}

/* Save image to computer
* @access public, @param string $destination, @return void */
public function Save($destination, $quality=60){
if($this->_extension == "png" || $this->_extension == "gif"){
imagesavealpha($this->_image_resource, true);
}
switch ($this->_extension) {
case "jpg": imagejpeg($this->_image_resource,$destination, $quality); break;
case "gif": imagegif($this->_image_resource,$destination); break;
default: $this->showError('Failed to save image!'); break;
}
}

/* Print image to screen
* @access public, @return void */
public function Parse($quality=60){
$name = $this->generateCacheName();
$content = "";
if(!$this->_cache || ($this->_cache && $this->cacheExpired())){
ob_start();
header ("Content-type: " . $this->_mime);
if($this->_extension == "png" || $this->_extension == "gif"){
imagesavealpha($this->_image_resource, true);
}

switch ($this->_extension) {
case "jpg": imagejpeg($this->_image_resource, "", $quality); break;
case "gif": imagegif($this->_image_resource); break;
default: $this->showError('Failed to save image!'); break;
}

$content = ob_get_contents();
ob_end_clean();
}else{

if (isset ($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
if (strtotime ($_SERVER['HTTP_IF_MODIFIED_SINCE']) < strtotime('now')) {
header ('HTTP/1.1 304 Not Modified');
die ();
}
}

// change the modified headers
$gmdate_expires = gmdate ('D, d M Y H:i:s', strtotime ('now +10 days')) . ' GMT';
$gmdate_modified = gmdate ('D, d M Y H:i:s') . ' GMT';

header ("Content-type: " . $this->_mime);
header ('Accept-Ranges: bytes');
header ('Last-Modified: ' . $gmdate_modified);
header ('Cache-Control: max-age=864000, must-revalidate');
header ('Expires: ' . $gmdate_expires);

echo $this->cachedImage($name);
exit();
}

// Save image content
if(!empty($content) && $this->_cache){
$this->cacheImage($name, $content);
}

// Destroy image
$this->Destroy();

echo $content;
exit();
}

/* Destroy resources
* @access public, @return void */
public function Destroy(){
imagedestroy($this->_image_resource);
}


/* Get image resources
* @access public, @return resource */
public function GetResource(){
return $this->_image_resource;
}

/* Set image resources
* @access public, @param resource $image, @return resource */
public function SetResource($image){
$this->_image_resource = $image;
}

/* Enable caching
* @access public, @param string $folder, @param int $ttl, * @return void */
public function EnableCache($folder="/var/www/vhosts/blabla.org/httpdocs/tmp/", $ttl=345600){
if(!is_dir($folder)){
$this->showError("Directory '" . $folder . "' does'nt exist");
}else{
$this->_cache = true;
$this->_cache_folder = $folder;
$this->_cache_ttl = $ttl;
}
return false;
}
}

The original author granted me permission for placing parts of code in here for solving this issue.


最佳答案

如果我对问题的理解正确,这完全是意料之中的。图像处理很慢。

黄色是您的浏览器发送请求。绿色是您的浏览器在等待服务器实际创建缩略图,无论服务器使用什么库,这都会花费大量时间。蓝色是发送响应的服务器,与前面的步骤不同,它受文件大小的影响。

对于图像处理固有的缓慢性,没有什么可做的。缓存这些缩略图是明智的,这样它们只生成一次,然后静态提供。这样,您的用户中很少有人会不得不忍受绿色延迟,您的服务器也会很高兴。

编辑:如果问题是这些 URL 中存在文件,但您的 RewriteRule 无论如何都会启动,请记住,默认情况下,规则运行时没有检查文件是否存在。

RewriteRule 上方使用以下条件来确保文件存在。

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule # ...etc...

关于PHP 缩略图图像生成器缓存 : How to set If-Last-Modified/Max-Age/Last-Modified HEADERS correctly in PHP?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5277935/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com