PHP代码在特定条件下运行两次


PHP code running twice under certain conditions

我遇到了这个奇怪的问题,当满足某些条件时,我的PHP代码运行两次。我的代码将水印添加到JPEG图像(在PHP中完成,允许我在必要时快速更改水印),并根据要求调整大小。为了加快请求,处理后的图像被缓存。每当加载图像时,我都会增加一个视图计数器,但是当以下情况发生时,计数器会增加2:

  • 在GET请求中设置了宽度或高度
  • 设置了输出MIME类型(注释掉header()调用将按预期运行脚本
  • 调用
  • imagecreatefromjpeg()并调整图像大小-当这些行被注释掉时,脚本正常运行。如果图像没有调整大小,脚本也可以正常运行。
  • 浏览器为Firefox。Internet Explorer 11运行正常,登录日志确认。(我没有测试过其他浏览器)

下面是我的代码:

<?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;
    }
}

这是怎么回事?

深夜搜索了一下,回答了我的问题——原来Firefox有一个bug,导致它在直接加载动态生成的图像时加载两次。当通过<img>标签加载时,它很好,所有其他浏览器行为正常。其他有此问题的人可以看看:)