[PHP] [原创]  WordPress 使用Ajax钩子 wp_ajax_{$ACTION} 显示图像时图像破埙

首先介绍一下WordPress用于处理Ajax请求的钩子:

wp_ajax_{$ACTION} 和 wp_ajax_nopriv_{$ACTION}

在用户已经登录的时候执行前者,否则执行后者。


前端Ajax请求示例:

JavaScript

jQuery.ajax({
    url: '<?php echo admin_url('admin-ajax.php') ?>',
    data: {
        action: 'my_action',
        str: '123'
    },
    success: function(data){
        alert(data);
    }
});

这里使用了 admin_url('admin-ajax.php') 来确保获得正确的请求文件。


或者直接使用URL GET请求:

PHP

admin_url( 'admin-ajax.php' ) . '?action=my_action&str=123'


后台处理请求示例:

PHP

add_action( 'wp_ajax_my_action', 'my_action_handler' );
add_action( 'wp_ajax_nopriv_my_action', 'my_action_handler' );

function my_action_handler(){
    $str = $_POST['str'];
    $str .= '456';
    echo $str;

    exit;
}

这里为了方便,把两个钩子绑定到同个函数。

注意函数结尾需要加上 exit; 或者 wp_die(); ,因为 admin_ajax.php 默认会输出0

这样使用了自带的钩子函数,就不必创建一个新文件来处理请求。


进入正题:最近更新一个微信自定义图标插件,原先插件是使用一个php文件来显示一个大小调整后的图像。

PHP

<?php
if(isset($_GET['src'])){
    $src = urldecode($_GET['src']);
}else{
    exit;
}
$width = 300;
$height = 300;

resizeImg($src,$width,$height);

function resizeImg($src,$width,$height){
    $arr = getimagesize($src);  

    header("Content-type: image/png");
    $ext = pathinfo($src, PATHINFO_EXTENSION);
    switch(strtolower($ext)){
        case 'jpg':
        case 'jpeg':
            $src = imagecreatefromjpeg($src);
            break;
        case 'gif':
            $src = imagecreatefromgif($src);
            break;
        case 'png':
            $src = imagecreatefrompng($src);
            break;
        case 'wbmp':
            $src = imagecreatefromwbmp($src);
            break;
        default:
            exit;
    }
    //$src = imagecreatefromjpeg($src);
    $image = imagecreatetruecolor($width, $height);
    $bg = imagecolorallocate($image, 255, 255, 255);
    imagefill($image, 0, 0, $bg);
    imagecopyresampled($image, $src, 0, 0, 0, 0, $width, $height, $arr[0], $arr[1]);
    imagepng($image);
    imagedestroy($image);
}
?>

图像调用链接是:http://localhost/wordpress/wp-content/plugins/wechatshare/ws-resize.php?src=http%3A%2F%2Flocalhost%2Fwordpress%2Fwp-content%2Fuploads%2F2016%2F09%2F343.jpg

一切显示正常。然后想改用钩子的方式来显示图像:

PHP

add_action( 'wp_ajax_nopriv_resize_img', 'ws_resize_img' );
add_action( 'wp_ajax_resize_img', 'ws_resize_img' );

//resize
function ws_resize_img(){
    if(isset($_GET['src'])){
        $src = urldecode($_GET['src']);
    }else{
        exit;
    }

    $width = 300;
    $height = 300;
    $arr = getimagesize($src);  

    header("Content-type: image/png");
    $ext = pathinfo($src, PATHINFO_EXTENSION);
    switch(strtolower($ext)){
        case 'jpg':
        case 'jpeg':
            $src = imagecreatefromjpeg($src);
            break;
        case 'gif':
            $src = imagecreatefromgif($src);
            break;
        case 'png':
            $src = imagecreatefrompng($src);
            break;
        case 'wbmp':
            $src = imagecreatefromwbmp($src);
            break;
        default:
            exit;
    }
    //$src = imagecreatefromjpeg($src);
    $image = imagecreatetruecolor($width, $height);
    $bg = imagecolorallocate($image, 255, 255, 255);
    imagefill($image, 0, 0, $bg);
    imagecopyresampled($image, $src, 0, 0, 0, 0,$width,$height,$arr[0], $arr[1]);
    imagepng($image);
    imagedestroy($image);

    exit;
}

图像调用链接是:http://localhost/wordpress/wp-admin/admin-ajax.php?action=resize_img&src=http%3A%2F%2Flocalhost%2Fwordpress%2Fwp-content%2Fuploads%2F2016%2F09%2F343.jpg

然后发现图像怎么也显示不出来了,显示为一张破埙的图像。


在WordPress官方论坛发帖,发现有可能是 header already sent 错误,但是查看错误日志也没有发现有错。

后来直接F12查看对比了正常图像和破埙图像的数据,发现破埙图像的数据前面多了几个字符的输出。果然还是F12好用。

正常图像  破埙图像

马上想到有可能是哪个插件输出了字符。

禁用掉所有插件只留下我的插件,一切正常了。

但是在实际环境中难免会有插件输出字符,不可能要求用户去禁用插件,所以只能自己去避免:

在 header("Content-type: image/png"); 前面加上两行:

PHP

ob_get_clean();
ob_clean();
在输出图片之前先把之前的输出清理掉,保证输出的是完整的图片。

问题就完美解决了。


附上更新后的WordPress自定义微信小图标插件:

已整合到单个PHP文件

http://www.qwqoffice.com/article-20.html

发表您的留言