我遇到这个奇怪的问题,当满足某些条件时,我的PHP代码会运行两次。我的代码为JPEG图像添加了水印(在PHP中完成,以便我可以在必要时快速更改水印),并在需要时调整大小。为了加速请求,处理的图像被缓存。无论何时加载图像,我都会递增视图计数器,但是当发生以下情况时,计数器会增加2:
header()
调用按预期运行脚本imagecreatefromjpeg()
并调整图像大小 - 当这些行被注释掉时,脚本会正常运行。如果未调整图像大小,脚本也会正常运行。这是我的代码:
<?php
require_once("../config.php");
if (empty($_GET['photoid'])) {
header("Location: /photos");
die();
}
$photoId = intval($_GET['photoid']);
$photo = getPhotoData($photoId);
if ($photo == null) {
http_response_code(404);
echo "That photo doesn't exist.";
} else {
$filename = $photo['photo_filename'];
$largePath = "large/";
$cachePath = $largePath . "view_cache/";
$cache = false;
if (!isset($_GET['admin']) && !isset($_GET['thumb']) && !isset($_GET['tile'])) {
incrementPhotoViewCount($photoId);
}
if (isset($_GET['height'])) {
list($originalWidth, $originalHeight) = getimagesize($largePath . $photo['photo_filename']);
$height = min(intval($_GET['height']), $originalHeight);
if (file_exists($cachePath . $height . "h" . $filename)) {
$im = imagecreatefromjpeg($cachePath . $height . "h" . $filename);
$cache = true;
} else {
$im = resizeImage($largePath . $photo['photo_filename'], $originalWidth, $height);
}
} else if (isset($_GET['width'])) {
list($originalWidth, $originalHeight) = getimagesize($largePath . $photo['photo_filename']);
$width = min(intval($_GET['width']), $originalWidth);
if (file_exists($cachePath . $width . "w" . $filename)) {
$im = imagecreatefromjpeg($cachePath . $width . "w" . $filename);
$cache = true;
} else {
$im = resizeImage($largePath . $photo['photo_filename'], $width, $originalHeight);
}
} else {
if (file_exists($cachePath . $filename)) {
$im = imagecreatefromjpeg($cachePath . $filename);
$cache = true;
} else {
$im = imagecreatefromjpeg($largePath . $photo['photo_filename']);
}
}
if (!$cache && ((!isset($height) || $height > 400) && (!isset($width) || $width > 350))) {
$watermark = imagecreatefrompng("../images/watermark.png");
//Preserve original watermark transparency
imagealphablending($watermark, true); // setting alpha blending on
imagesavealpha($watermark, true); // save alphablending setting (important)
//Set the margins for the watermark and get the height/width of the stamp image
$marginLeft = 20;
$marginBottom = 20;
$sx = imagesx($watermark);
$sy = imagesy($watermark);
//Merge the stamp onto our photo
imagecopy($im, $watermark, $marginLeft, imagesy($im) - $sy - $marginBottom, 0, 0, $sx, $sy);
}
//Output the image and free memory
header("Content-Type: image/jpeg");
imagejpeg($im);
if (!$cache) {
if (isset($_GET['height'])) {
imagejpeg($im, $cachePath . $height . "h" . $filename);
} else if (isset($_GET['width'])) {
imagejpeg($im, $cachePath . $width . "w" . $filename);
} else {
imagejpeg($im, $cachePath . $filename);
}
}
imagedestroy($im);
}
function resizeImage($file, $w, $h, $crop = false) {
list($width, $height) = getimagesize($file);
$r = $width / $height;
if ($crop) {
if ($width > $height) {
$width = ceil($width-($width*abs($r-$w/$h)));
} else {
$height = ceil($height-($height*abs($r-$w/$h)));
}
$newwidth = $w;
$newheight = $h;
} else {
if ($w/$h > $r) {
$newwidth = $h*$r;
$newheight = $h;
} else {
$newheight = $w/$r;
$newwidth = $w;
}
}
$src = imagecreatefromjpeg($file);
$dst = imagecreatetruecolor($newwidth, $newheight);
imagecopyresampled($dst, $src, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
return $dst;
}
这是更新视图计数器的代码:
function incrementPhotoViewCount($photoId) {
$photoId = intval($photoId);
if (!($stmt = $GLOBALS['mysqli']->prepare("UPDATE `Photo` SET `view_count` = `view_count` + 1 WHERE `photo_id` = ?"))) {
error_log("Prepare failed: (" . $GLOBALS['mysqli']->errno . ") " . $GLOBALS['mysqli']->error);
return false;
}
if (!$stmt->bind_param("i", $photoId)) {
error_log("Binding parameters failed: (" . $stmt->errno . ") " . $stmt->error);
return false;
}
if (!$stmt->execute()) {
echo "Execute failed: (" . $stmt->errno . ") " . $stmt->error;
return false;
}
}
这里发生了什么?
答案 0 :(得分:1)
一些额外的深夜谷歌搜索回答了我的问题 - 结果Firefox has a bug which causes it to load dynamically generated images twice when loaded directly。通过<img>
标记加载时,它很好,所有其他浏览器的行为都正常。有问题的其他人可以看一下:)