CI4使用CodeIgniter S3库上传图片后访问URL报AccessDenied错误如何解决
问题原因
你当前代码中仅在putObject方法里配置了ACL => 'public-read'权限,但实际上传走的是ObjectUploader/MultipartUploader分片上传逻辑,初始化这两个上传类时没有传递公开访问的ACL参数,所以上传后的对象默认继承存储桶的私有权限,直接访问URL就会返回AccessDenied错误。
解决方案
方案1:修改上传代码,上传时指定公开权限
修改objectUploader方法,在初始化ObjectUploader和MultipartUploader时增加ACL、ContentType等配置,修改后的代码如下:
private function objectUploader($sourcePath, $destinationPath){ $source = fopen($sourcePath, 'rb'); // 新增上传配置项,指定ACL和文件类型 $uploadOptions = [ 'ACL' => 'public-read', 'ContentType' => mime_content_type($sourcePath), // 自动识别正确的图片MIME类型 'StorageClass' => 'STANDARD' ]; $uploader = new ObjectUploader( $this->s3Client, $this->bucket, $destinationPath, $source, $uploadOptions // 传入配置 ); do { try { $result = $uploader->upload(); if ($result["@metadata"]["statusCode"] == '200') { $this->data = $result; return true; } return FALSE; } catch (MultipartUploadException $e) { rewind($source); // 分片上传也传入同样的配置 $uploader = new MultipartUploader($this->s3Client, $source, [ 'state' => $e->getState(), 'bucket' => $this->bucket, 'key' => $destinationPath, 'ACL' => 'public-read', 'ContentType' => mime_content_type($sourcePath), 'StorageClass' => 'STANDARD' ]); $this->log_message($type = 'ERROR', $e->getMessage()); $this->data = $e->getMessage(); return FALSE; } } while (!isset($result)); }
方案2:配置存储桶公共访问策略(可选)
如果整个存储桶都是用来存储需要公开访问的静态资源,可以直接配置存储桶策略,无需每次上传都指定ACL,策略示例如下:
{ "Version": "2012-10-17", "Statement": [ { "Sid": "PublicReadGetObject", "Effect": "Allow", "Principal": "*", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::你的存储桶名称/*" } ] }
注意事项
- 操作前先确认S3存储桶的「阻止公共访问」设置中,未禁用公共ACL/公共访问,否则上传时指定
public-read会报错。 - 不要固定设置
ContentType为image,使用mime_content_type自动识别真实的MIME类型,避免浏览器访问图片时直接下载而非展示。
内容的提问来源于stack exchange,提问作者Mahmud Hasan Jion
相关产品推荐
相关产品推荐

