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

如何使用原生PHP展示存储在Amazon S3中的已上传图片?

存在的两个核心问题

  • 上传逻辑数据不匹配:上传到S3时使用的文件名为用户上传的原始文件名,写入数据库的post_image字段时你将文件名重新赋值为了时间戳格式,二者完全不一致,后续根本找不到对应的S3文件
  • 展示路径错误:当前图片标签指向的是本地服务器images/目录,你的图片实际存储在S3中,自然无法加载

修复步骤

1. 修改add_post.php上传逻辑

推荐直接将S3返回的永久访问地址存入数据库,省去后续拼接地址的步骤,同时统一文件名避免重复,修改后代码如下:

if(isset($_POST['create_post'])){
    if(!empty($_POST['post_contents'])){
        $post_image_url = '';
        if(isset($_FILES['image'])){
            // 生成唯一文件名避免重名覆盖
            $extension = pathinfo($_FILES['image']['name'], PATHINFO_EXTENSION);
            $file_name = date('YmdHis') . '.' . $extension;   
            $temp_file_location = $_FILES['image']['tmp_name']; 

            $s3 = new Aws\S3\S3Client([
                'region'  => 'ap-northeast-1',
                'version' => 'latest',
                'credentials' => [
                    // 建议把密钥存在Heroku环境变量,不要硬编码在代码里
                    'key'    => getenv('AWS_ACCESS_KEY_ID'),
                    'secret' => getenv('AWS_SECRET_ACCESS_KEY'),
                ]
            ]);     

            $result = $s3->putObject([
                'Bucket' => '替换为你的S3桶名',
                'Key'    => $file_name,
                'SourceFile' => $temp_file_location,
                // 按需设置公共读权限,如果你的桶默认公共可访问可以不加
                'ACL' => 'public-read'      
            ]);
            // 获取S3返回的永久访问地址
            $post_image_url = $result['ObjectURL'];
        }

        $post = $db->prepare('INSERT INTO posts SET post_user_id=?, post_contents=?, post_image=?, post_date=NOW()');
        $post->execute(array(
            $user['user_id'],
            $_POST['post_contents'],
            // 直接存S3的完整访问地址
            $post_image_url,
        ));
        
        header('Location: index.php');
        exit();
    }else{
        echo "<script>alert('Contents fields cannot be empty')</script>";
    }
}

2. 修改index.php展示逻辑

直接输出数据库中存储的S3访问地址即可:

<?php foreach ($posts as $post): ?>
<div class="post-preview">
      <a href="post.php?post_id=<?php echo htmlspecialchars($post['post_id']); ?>"><?php echo htmlspecialchars($post['post_contents']); ?></a>
      <?php if(!empty($post['post_image'])): ?>
      <p><img width='300' src="<?php echo htmlspecialchars($post['post_image'], ENT_QUOTES); ?>"></p>
      <?php endif; ?>
      <p class="postContents"><?php echo htmlspecialchars($post['post_date'], ENT_QUOTES); ?> | <?php echo htmlspecialchars($post['user_name'], ENT_QUOTES); ?></p>
  <hr class="my-4" />
</div>
<?php endforeach; ?>

补充注意事项

  • 提前配置S3桶的CORS规则,允许你的Heroku域名访问资源,否则图片会被跨域策略拦截
  • 如果不希望图片公开可访问,可以调用S3的getObjectUrl方法生成临时签名的访问地址,输出到前端即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 21:18:04