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

Laravel 11中OCI Bucket执行GetObjectAcl抛出异常问题排查

Laravel 11对接OCI对象存储:移动/复制文件失败排查与解决

问题背景

PHP 8.3环境下的Laravel 11项目,通过S3兼容的OCI对象存储URL对接Bucket时,文件上传、下载功能正常,但移动或复制文件操作失败。调试AwsS3V3Adapter文件发现,执行GetObjectAcl命令时抛出异常。当前使用OCI管理员用户的Customer secret key,需确认问题根源是OCI权限配置还是AWS S3适配器与OCI对象存储的兼容性问题。

配置信息

'oci' => [
    'driver' => 's3',
    'key' => env('OCI_ACCESS_KEY_ID'),
    'secret' => env('OCI_SECRET_ACCESS_KEY'),
    'region' => env('OCI_DEFAULT_REGION'),
    'bucket' => env('OCI_BUCKET'),
    'url' => env('OCI_URL') .  '/' .  env('OCI_BUCKET'),
    'endpoint' => env('OCI_URL'),
    'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', true),
    'throw' => true,
],

已做排查操作

  • 使用开启use_path_style_endpoint的默认S3配置;
  • 创建OCI专属服务提供者;
  • 测试默认URL、专用URL及S3兼容端点,仅S3兼容端点可正常上传;
  • 添加VisibilityAdapter;
  • 配置新的Compartment权限策略,但均未解决问题。

问题分析与解决方向

1. 权限配置可能性

虽然使用的是OCI管理员用户的密钥,但OCI的权限策略可能需要显式授权ACL相关操作。默认管理员权限未必包含objectstorage:GetObjectAcl和objectstorage:PutObjectAcl权限,尤其是自定义过Compartment策略时。

验证步骤:
在OCI控制台给该用户的策略中添加以下语句:

Allow user [用户名] to manage objectstorage-namespaces in compartment [ compartment名称 ]
Allow user [用户名] to manage objects in compartment [ compartment名称 ] where target.bucket.name='[Bucket名称]'

或者更精细地授权ACL操作:

Allow user [用户名] to perform objectstorage:GetObjectAcl in compartment [ compartment名称 ] where target.bucket.name='[Bucket名称]'
Allow user [用户名] to perform objectstorage:PutObjectAcl in compartment [ compartment名称 ] where target.bucket.name='[Bucket名称]'

添加后重试移动/复制操作,若恢复正常则说明是权限问题。

2. 适配器兼容性问题

OCI对象存储虽兼容S3 API,但对部分S3特有操作(如ACL复制)的支持存在差异。Laravel的AwsS3V3Adapter在执行移动/复制时,默认会尝试读取源对象的ACL并复制到目标对象,而OCI可能不支持该逻辑。

解决方法:
自定义适配器继承AwsS3V3Adapter,重写copy和move方法,跳过ACL操作:

use League\Flysystem\AwsS3V3\AwsS3V3Adapter;
use Aws\S3\S3Client;

class OciS3Adapter extends AwsS3V3Adapter
{
    public function __construct(S3Client $client, string $bucket, string $prefix = '')
    {
        parent::__construct($client, $bucket, $prefix);
    }

    public function copy(string $source, string $destination, array $config = []): void
    {
        $sourceKey = $this->applyPathPrefix($source);
        $destinationKey = $this->applyPathPrefix($destination);

        $this->client->copyObject([
            'Bucket' => $this->bucket,
            'Key' => $destinationKey,
            'CopySource' => "{$this->bucket}/{$sourceKey}",
            'MetadataDirective' => 'COPY',
            'ACL' => $config['visibility'] ?? $this->defaultVisibility,
        ]);
    }

    public function move(string $source, string $destination, array $config = []): void
    {
        $this->copy($source, $destination, $config);
        $this->delete($source);
    }
}

然后在Laravel的文件系统服务提供者中注册该适配器:

use Illuminate\Support\Facades\Storage;
use Illuminate\Support\ServiceProvider;
use Aws\S3\S3Client;
use App\Adapters\OciS3Adapter;

class FilesystemServiceProvider extends ServiceProvider
{
    public function boot()
    {
        Storage::extend('oci', function ($app, $config) {
            $client = new S3Client([
                'credentials' => [
                    'key' => $config['key'],
                    'secret' => $config['secret'],
                ],
                'region' => $config['region'],
                'endpoint' => $config['endpoint'],
                'use_path_style_endpoint' => $config['use_path_style_endpoint'],
                'version' => 'latest',
            ]);

            return new \League\Flysystem\Filesystem(new OciS3Adapter(
                $client,
                $config['bucket'],
                $config['prefix'] ?? ''
            ));
        });
    }
}

替换原有的OCI文件系统驱动配置后,重试移动/复制操作即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 10:08:22