You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP图片上传裁剪后显示(同页AJAX)及异常修复

问题分析与解决方案

先拆解你遇到的两个核心问题,再给出针对性的修复方案:

问题根源

1. 0字节空文件生成的原因

  • 变量作用域错误:你定义的display_image()函数无法访问if(isset($_POST['image']))块里的$image_name变量,导致输出的图片路径变成uploads/,浏览器请求这个目录时会间接触发空文件生成;
  • 重复提交问题:页面刷新时,浏览器可能会重复发送上次的POST请求,若此时没有有效图片数据,base64_decode($image)会得到空内容,写入文件就会生成0字节的无效文件;
  • 代码执行时机:你的PHP代码直接嵌入页面,每次加载都会运行,即使没有POST请求,变量未定义的问题也会间接引发异常。

2. 上传后图片无法显示的原因

  • display_image()函数中$image_name未在作用域内定义,生成的图片路径无效;
  • 前端AJAX成功回调仍在使用base64格式的图片,没有利用服务器返回的实际文件URL。

具体修复步骤

步骤1:修正PHP逻辑,解决变量作用域与空文件问题

调整PHP代码,添加数据验证,确保只有有效POST请求才处理图片,同时确保uploads目录存在:

<?php
session_start(); // 开启会话用于处理重定向

if(isset($_POST['image'])){
    $image = $_POST['image'];
    // 验证图片数据格式
    if (strpos($image, 'data:image/') !== 0) {
        echo json_encode(['status' => 'error', 'message' => '无效的图片数据']);
        exit;
    }
    list($type, $image) = explode(';',$image);
    list(, $image) = explode(',',$image);
    $image = base64_decode($image);
    
    // 验证base64解码是否成功
    if ($image === false) {
        echo json_encode(['status' => 'error', 'message' => '图片解码失败']);
        exit;
    }
    
    $image_name = time().'.png';
    $upload_path = 'uploads/'.$image_name;
    // 确保uploads目录存在
    if (!file_exists('uploads')) {
        mkdir('uploads', 0755, true);
    }
    file_put_contents($upload_path, $image);
    
    // 使用Post/Redirect/Get模式避免重复提交
    $_SESSION['uploaded_image'] = $upload_path;
    header('Location: ' . $_SERVER['PHP_SELF']);
    exit;
}
?>

步骤2:修改前端AJAX,使用服务器返回的图片URL

调整前端代码,移除base64显示逻辑,改用服务器实际文件路径:

$('.btn-upload-image').on('click', function () {
    resize.croppie('result', {
        type: 'canvas',
        size: 'viewport'
    }).then(function (img) {
        $.ajax({
            type: "POST",
            url: window.location.href,
            data: {"image":img},
            dataType: 'json',
            error: function() {
                // 重定向后AJAX会收到302响应,这里刷新页面显示图片
                window.location.reload();
            }
        });
    });
});

步骤3:添加页面内的图片显示逻辑

在页面顶部添加代码,通过会话存储的路径显示上传后的图片:

<div class="container">
<?php
if (isset($_SESSION['uploaded_image'])) {
    echo '<div class="mb-3">上传预览:<img src="' . $_SESSION['uploaded_image'] . '" width="70" height="70" ></div>';
    unset($_SESSION['uploaded_image']); // 显示后清除会话,避免重复显示
}
?>
<!-- 原有页面内容 -->
</div>

步骤4:移除无效的display_image()函数

原函数因变量作用域问题无法正常工作,且我们已通过会话和AJAX实现图片显示,直接移除该函数及相关调用即可。


完整修正后的代码

<?php
session_start();
if(isset($_POST['image'])){
    $image = $_POST['image'];
    if (strpos($image, 'data:image/') !== 0) {
        echo json_encode(['status' => 'error', 'message' => '无效的图片数据']);
        exit;
    }
    list($type, $image) = explode(';',$image);
    list(, $image) = explode(',',$image);
    $image = base64_decode($image);
    
    if ($image === false) {
        echo json_encode(['status' => 'error', 'message' => '图片解码失败']);
        exit;
    }
    
    $image_name = time().'.png';
    $upload_path = 'uploads/'.$image_name;
    if (!file_exists('uploads')) {
        mkdir('uploads', 0755, true);
    }
    file_put_contents($upload_path, $image);
    
    $_SESSION['uploaded_image'] = $upload_path;
    header('Location: ' . $_SERVER['PHP_SELF']);
    exit;
}
?>
<html lang="en">
<head>
<title>PHP and jQuery - Crop Image and Upload using Croppie plugin</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.1/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/croppie/2.6.2/croppie.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/croppie/2.6.2/croppie.js"></script>
<meta name="csrf-token" content="{{ csrf_token() }}">
</head>
<body>
<div class="container">
<?php
if (isset($_SESSION['uploaded_image'])) {
    echo '<div class="mb-3">上传预览:<img src="' . $_SESSION['uploaded_image'] . '" width="70" height="70" ></div>';
    unset($_SESSION['uploaded_image']);
}
?>
<div class="card" style="max-height: 500px;">
<div class="card-header bg-info">PHP and jQuery - Crop Image and Upload using Croppie plugin</div>
<div class="card-body">
<div class="row">
<div class="col-md-4 text-center">
<div id="upload-demo"></div>
</div>
<div class="col-md-4" style="padding:5%;">
<strong>选择图片裁剪:</strong>
<input type="file" id="image">
<button class="btn btn-success btn-block btn-upload-image" style="margin-top:2%">上传图片</button>
</div>
<div class="col-md-4">
<div id="preview-crop-image" style="background:#9d9d9d;width:300px;padding:50px 50px;height:300px;"></div>
</div>
</div>
</div>
</div>
</div>
<script type="text/javascript">
var resize = $('#upload-demo').croppie({
enableExif: true,
enableOrientation: true,
viewport: {
width: 200,
height: 200,
type: 'circle'
},
boundary: {
width: 300,
height: 300
}
});

$('#image').on('change', function () {
var reader = new FileReader();
reader.onload = function (e) {
resize.croppie('bind',{
url: e.target.result
}).then(function(){
console.log('图片绑定完成');
});
}
reader.readAsDataURL(this.files[0]);
});

$('.btn-upload-image').on('click', function () {
resize.croppie('result', {
type: 'canvas',
size: 'viewport'
}).then(function (img) {
$.ajax({
type: "POST",
url: window.location.href,
data: {"image":img},
dataType: 'json',
error: function() {
window.location.reload();
}
});
});
});
</script>
</body>
</html>

额外注意事项

  • 确保服务器对uploads目录有写入权限,否则图片无法保存;
  • 若使用Laravel框架(看到你用到了{{ csrf_token() }}),建议将上传逻辑移至控制器,更符合框架规范;
  • 可添加文件大小、类型验证,防止上传恶意文件或过大图片。

内容的提问来源于stack exchange,提问作者John

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 09:18:08