使用 PHP 与 AWS SDK 开发 Ceph RGW(S3 兼容)应用:从连接创建到签名 URL 的完整指南
存储分布式文件系统对象存储后端高可用【免费下载链接】cephCeph is a distributed object, block, and file storage platform项目地址https://gitcode.com/gh_mirrors/ce/ceph点击查看免费下载本文以 Ceph 对象网关RADOS Gateway简称 RGW的 S3 兼容接口为核心基于官方文档 doc/radosgw/s3/php.rst 的 PHP 示例系统讲解如何通过 AWS PHP SDK 完成连接创建、桶与对象的增删改查、ACL 权限控制以及签名 URL 生成等完整操作。读完本文你将能够在自己的 PHP 项目中用最少的代码把 Ceph RGW 当作标准 S3 服务使用并理解每个 API 调用背后的服务端行为与分页、权限等关键细节。环境准备安装 AWS PHP SDK在开始编写代码之前需要先安装 AWS 官方 PHP SDKaws/aws-sdk-php。Ceph RGW 兼容 S3 协议因此该 SDK 是官方推荐且兼容性最好的 PHP 客户端之一。如果你还没有安装 ComposerPHP 的依赖管理工具请先完成 Composer 的安装然后在项目根目录执行$ composer install aws/aws-sdk-php安装完成后Composer 会生成vendor/目录与自动加载文件vendor/autoload.php后续所有示例代码都通过require __DIR__./vendor/autoload.php;引入 SDK。创建与 RGW 服务的连接与任何 S3 兼容服务交互的第一步是实例化Aws\S3\S3Client。针对 Ceph RGW初始化参数有四个关键点regionCeph RGW 不依赖 AWS 区域概念但 SDK 强制要求该字段因此置为空字符串version指定 S3 API 版本Ceph 文档中的示例使用2006-03-01endpointRGW 服务地址例如http://objects.dreamhost.com示例为外部兼容服务接入自建 Ceph RGW 时替换为你的网关地址如http://ceph-rgw.example.comuse_path_style_endpoint置为true让 SDK 使用endpoint/bucket的路径风格寻址而不是bucket.endpoint的虚拟主机风格。?php use Aws\S3\S3Client; define(AWS_KEY, place access key here); define(AWS_SECRET_KEY, place secret key here); $ENDPOINT http://objects.dreamhost.com; // require the Amazon SDK from your composer vendor dir require __DIR__./vendor/autoload.php; // Instantiate the S3 class and point it at the desired host $client new S3Client([ region , version 2006-03-01, endpoint $ENDPOINT, credentials [ key AWS_KEY, secret AWS_SECRET_KEY ], // Set the S3 class to use objects.dreamhost.com/bucket // instead of bucket.objects.dreamhost.com use_path_style_endpoint true ]);提示AWS_KEY与AWS_SECRET_KEY对应 RGW 为用户分配的 Access Key 与 Secret Key。在生产环境中应通过环境变量、配置文件或密钥管理服务注入避免硬编码在源码中。路径风格与虚拟主机风格use_path_style_endpoint涉及 S3 两种桶寻址模式详见 doc/radosgw/s3/commons.rst路径风格path-style桶名作为请求路径的顶级目录例如GET /mybucket HTTP/1.1Host: cname.domain.com虚拟主机风格virtual-hosted-style桶名作为完全限定域名的一部分例如GET / HTTP/1.1Host: mybucket.cname.domain.com这也是多数 S3 客户端默认采用的方式。AWS 已宣布逐步废弃路径风格访问但 Ceph RGW 同时支持两种模式。若你希望 RGW 正确处理带桶名的主机头需要在 Monitor 配置库中设置rgw_dns_name或在 zonegroup 配置的hostnames列表中声明网关域名ceph config set client.rgw.ceph authx client for rgw rgw_dns_name cname.domain.com从源码看RGW 在 src/rgw/rgw_rest.cc 中读取rgw_dns_name并按逗号与空格拆分出多个合法主机名get_str_list(rgw_dns_names_str, , , rgw_dns_names)随后在第 2161 行将其作为请求的 domain 字段参与桶名解析。因此该参数直接决定了虚拟主机风格访问能否命中正确的桶在 PHP SDK 中显式设置use_path_style_endpoint true则可以绕开 DNS 解析环节直接以路径风格访问。补充当 RGW 部署在反向代理之后时应使用代理的 DNS 名启用 SSL 时证书需要包含匹配桶子域名的通配符S3 静态网站视图s3websiteAPI使用独立的rgw_dns_s3website_name配置与rgw_dns_name分开设置。桶Bucket操作列出用户拥有的桶listBuckets()返回一个AWS\Result实例可以用数组下标方式访问。下面代码遍历所有桶并打印桶名与创建时间?php $listResponse $client-listBuckets(); $buckets $listResponse[Buckets]; foreach ($buckets as $bucket) { echo $bucket[Name] . \t . $bucket[CreationDate] . \n; }输出类似mahbuckat1 2011-04-21T18:05:39.000Z mahbuckat2 2011-04-21T18:05:48.000Z mahbuckat3 2011-04-21T18:07:18.000Z创建桶创建一个名为my-new-bucket的桶同样返回AWS\Result对象?php $client-createBucket([Bucket my-new-bucket]);创建时可通过ACL参数直接指定桶级 canned ACL也可稍后用putBucketAcl修改。若同名桶已存在RGW 会返回409 BucketAlreadyExists见 doc/radosgw/s3/commons.rst 的公共响应码表。列出桶中的对象listObjects返回桶内对象列表每个对象包含Key对象名、Size字节大小与LastModified最后修改时间?php $objectsListResponse $client-listObjects([Bucket $bucketname]); $objects $objectsListResponse[Contents] ?? []; foreach ($objects as $object) { echo $object[Key] . \t . $object[Size] . \t . $object[LastModified] . \n; }输出类似myphoto1.jpg 251262 2011-08-08T21:35:48.000Z myphoto2.jpg 262518 2011-08-08T21:38:01.000Z注意重要如果桶内对象超过 1000 个一次listObjects无法返回全部结果。此时必须检查响应中的isTruncated字段若为true则把本次结果最后一个对象的 Key 作为Marker参数再次请求循环直到isTruncated不再为真。?php $marker null; do { $params [Bucket $bucketname]; if ($marker ! null) { $params[Marker] $marker; } $response $client-listObjects($params); foreach (($response[Contents] ?? []) as $object) { echo $object[Key] . \t . $object[Size] . \t . $object[LastModified] . \n; $marker $object[Key]; } } while ($response[IsTruncated]);这一分页行为在 RGW 服务端有硬性约束从源码看RGW 默认单页最多返回 1000 个条目src/rgw/driver/rados/rgw_bucket.cc 中constexpr uint64_t max_keys 1000;并且 RGW 会对客户端传入的max-keys做安全钳制——RGWListBucket::parse_max_keys()将max-keys绑定在 0 到配置上限之间src/rgw/rgw_op.cc并在 src/rgw/rgw_op.cc 中以do...while (results.is_truncated)形式消费所有分页。因此客户端侧务必实现上述游标循环才能完整枚举大桶。删除桶删除名为my-old-bucket的桶?php $client-deleteBucket([Bucket my-old-bucket]);注意重要桶必须为空才能删除如果桶内仍有对象RGW 会返回409 BucketNotEmpty。正确流程是先枚举并删除桶内所有对象可配合deleteObjects批量删除再删除桶。对象Object操作上传对象putObject将字符串内容写入指定桶的对象。下面创建一个内容为Hello World!的hello.txt?php $client-putObject([ Bucket my-bucket-name, Key hello.txt, Body Hello World! ]);Body可以是字符串、资源流或Psr\Http\Message\StreamInterface实现因此也适用于上传本地文件或大文件流大文件建议改用MultipartUploader进行分片上传。修改对象的 ACL对象默认继承桶的权限策略默认私有。putObjectAcl允许对单个对象设置 canned ACL。下面把hello.txt设为公开可读把secret_plans.txt设为私有?php $client-putObjectAcl([ Bucket my-bucket-name, Key hello.txt, ACL public-read ]); $client-putObjectAcl([ Bucket my-bucket-name, Key secret_plans.txt, ACL private ]);这些 canned ACL 在 RGW 服务端的语义由 src/rgw/rgw_acl_s3.cc 中的create_canned()函数实现规则如下canned ACL服务端实现对应源码分支private或空仅所有者拥有FULL_CONTROL不附加任何授权L420-L422public-read所有者FULL_CONTROL 所有用户组ACL_GROUP_ALL_USERS获得READL424-L427public-read-write所有者FULL_CONTROL 所有用户组获得READ与WRITEL428-L433authenticated-read所有者FULL_CONTROL 已认证用户组获得READL434-L437bucket-owner-read/bucket-owner-full-control当桶所有者与对象所有者不同时授予桶所有者对应权限L438-L449从源码可以确认public-read的本质是向匿名用户组授予读权限这正是后续未签名 URL 能够直接访问hello.txt的原因而private对象只有所有者可访问必须借助签名 URL。删除对象删除名为goodbye.txt的对象?php $client-deleteObject([Bucket my-bucket-name, Key goodbye.txt]);下载对象到本地文件getObject返回对象内容Body是一个流对象可通过getContents()取回完整内容并写入本地文件。下面把poetry.pdf下载到/home/larry/documents/?php $object $client-getObject([Bucket my-bucket-name, Key poetry.pdf]); file_put_contents(/home/larry/documents/poetry.pdf, $object[Body]-getContents());对于大对象更推荐把Body流直接拷贝到本地文件句柄例如用GuzzleHttp\Psr7\Stream与copy_to_stream避免一次性把整个对象载入内存。生成对象下载 URL签名与未签名Ceph RGW 支持通过预签名 URLpresigned URL向他人提供限时下载能力也支持为公开对象直接生成未签名 URL。未签名 URL使用getObjectUrl生成仅对公开对象有效如上面设置了public-read的hello.txt签名 URL先通过getCommand(GetObject, ...)构造命令再用createPresignedRequest指定有效期。签名 URL 在有效期内即使对象是私有的也能下载到期后自动失效。?php $hello_url $client-getObjectUrl(my-bucket-name, hello.txt); echo $hello_url.\n; $secret_plans_cmd $client-getCommand(GetObject, [Bucket my-bucket-name, Key secret_plans.txt]); $request $client-createPresignedRequest($secret_plans_cmd, 1 hour); echo $request-getUri().\n;输出类似http://objects.dreamhost.com/my-bucket-name/hello.txt http://objects.dreamhost.com/my-bucket-name/secret_plans.txt?X-Amz-Content-Sha256UNSIGNED-PAYLOADX-Amz-AlgorithmAWS4-HMAC-SHA256X-Amz-CredentialsandboxAccessKey%2F20190116%2F%2Fs3%2Faws4_requestX-Amz-Date20190116T125520ZX-Amz-SignedHeadershostX-Amz-Expires3600X-Amz-Signature61921f07c73d7695e47a2192cf55ae030f34c44c512b2160bb5a936b2b48d923从生成的 URL 可以看到签名机制的几个关键参数X-Amz-AlgorithmAWS4-HMAC-SHA256表明使用 AWS 签名 V4 算法RGW 在 src/rgw/rgw_auth.h 中实现了对 AWS Auth V4 的解析与过滤X-Amz-Credential包含 Access Key 与签发时间X-Amz-Expires3600表示有效期 3600 秒即 1 小时X-Amz-Signature是对请求的 HMAC-SHA256 签名。浏览器直接访问该 URL 即可下载无需携带任何凭证——这正是预签名 URL 适合分发给临时用户的典型用法。常见错误码速查使用 PHP SDK 与 RGW 交互时SDK 会将服务端返回的 HTTP 状态码转换为对应的S3Exception。结合 doc/radosgw/s3/commons.rst 的公共响应码表以下几个状态码在 PHP 开发中最常遇到HTTP 状态码错误码触发场景400InvalidBucketName/InvalidObjectName桶名或对象名不符合 S3 命名规范403AccessDenied凭证缺失、签名错误或权限不足如访问私有对象404NoSuchBucket/NoSuchKey桶或对象不存在409BucketAlreadyExists创建已存在的桶409BucketNotEmpty删除非空桶500InternalErrorRGW 服务端内部错误捕获异常的推荐写法?php use Aws\Exception\S3Exception; try { $client-getObject([Bucket my-bucket-name, Key missing.txt]); } catch (S3Exception $e) { echo HTTP 状态码: . $e-getStatusCode() . \n; echo 错误码: . $e-getAwsErrorCode() . \n; echo 错误信息: . $e-getAwsErrorMessage() . \n; }完整示例一键串联全流程将上述各步骤整合为一个可独立运行的脚本便于快速验证 RGW 环境?php use Aws\S3\S3Client; use Aws\Exception\S3Exception; require __DIR__./vendor/autoload.php; $client new S3Client([ region , version 2006-03-01, endpoint http://ceph-rgw.example.com, // 替换为你的 RGW 地址 credentials [ key YOUR_ACCESS_KEY, secret YOUR_SECRET_KEY, ], use_path_style_endpoint true, ]); $bucket demo-bucket- . time(); // 1. 创建桶 $client-createBucket([Bucket $bucket]); // 2. 上传对象 $client-putObject([ Bucket $bucket, Key hello.txt, Body Hello World!, ]); // 3. 设为公开读 $client-putObjectAcl([ Bucket $bucket, Key hello.txt, ACL public-read, ]); // 4. 列出对象 $objects $client-listObjects([Bucket $bucket])[Contents] ?? []; foreach ($objects as $object) { echo $object[Key] . \t . $object[Size] . \t . $object[LastModified] . \n; } // 5. 生成签名 URL1 小时有效 $cmd $client-getCommand(GetObject, [Bucket $bucket, Key hello.txt]); $presigned $client-createPresignedRequest($cmd, 1 hour); echo $presigned-getUri() . \n; // 6. 删除对象与桶先清空桶 $client-deleteObject([Bucket $bucket, Key hello.txt]); $client-deleteBucket([Bucket $bucket]);总结通过 AWS PHP SDK 访问 Ceph RGW 的完整路径可以概括为composer安装 SDK → 以空 region、自定义 endpoint 与路径风格初始化S3Client→ 依次完成桶与对象的增删改查、ACL 设置与预签名 URL 生成。理解use_path_style_endpoint与rgw_dns_name的对应关系、listObjects的 1000 条分页上限、canned ACL 在 src/rgw/rgw_acl_s3.cc 中的实现语义以及 AWS4-HMAC-SHA256 签名 URL 的生成机制能帮助你在实际项目中少走弯路把 Ceph RGW 稳定、安全地接入 PHP 应用。更多语言示例可参考 doc/radosgw/s3 目录下的 Python、Java、Ruby 等对应文档。赞分享存储分布式文件系统对象存储后端高可用【免费下载链接】cephCeph is a distributed object, block, and file storage platform项目地址https://gitcode.com/gh_mirrors/ce/ceph点击查看免费下载相关推荐使用 C AWS SDK 对接 Ceph RGW S3 网关从连接建立、桶与对象操作到预签名 URL 的完整实践使用 C AWS SDK 对接 Ceph RGW S3 网关从连接建立、桶与对象操作到预签名 URL 的完整实践 本文以 Ceph RADOS Gateway存储分布式文件系统对象存储后端高可用使用 Ruby AWS SDK 访问 Ceph RGW S3 接口桶与对象操作完整指南使用 Ruby AWS SDK 访问 Ceph RGW S3 接口桶与对象操作完整指南 导读 Ceph Object GatewayRGW对外提供与 Am存储分布式文件系统对象存储后端高可用Ceph RGW S3 兼容性测试套件从 s3-tests 到 STS / IAM / Bucket Logging 的完整实战指南Ceph RGW S3 兼容性测试套件从 s3 tests 到 STS / IAM / Bucket Logging 的完整实战指南 本指南基于 Ceph 仓存储分布式文件系统对象存储后端高可用创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

星图识别全解析:从几何特征到姿态解算的工程实践

星图识别全解析:从几何特征到姿态解算的工程实践

简介:面向天文观测、航天导航与星图识别应用场景的MATLAB实现工具包,围绕星图识别全流程组织代码,适合需要开展星体特征提取、位置解算或BP网络识别实验的研究人员、工程师与相关专业学生。资源共18个文件,以15个m脚本为主&#x…

2026/9/25 3:33:58 阅读更多 →
基于深度学习与TCN的京东商品销量预测:从数据管道到补货决策

基于深度学习与TCN的京东商品销量预测:从数据管道到补货决策

简介:一套基于深度学习的京东商品销量预测完整源码,面向电商数据分析人员、机器学习开发者及参赛者,可用于学习销量预测建模、数据清洗、特征生成与模型评估全流程。包体共51个文件、约6.96MB,以Python源码、SQL脚本、CSV数据与PN…

2026/9/25 13:18:19 阅读更多 →
GAN文字图像修复:结构-语义联合重建实战

GAN文字图像修复:结构-语义联合重建实战

简介:本资源是一套基于生成对抗网络(GAN)实现复杂背景文字图像修复的完整Python开源项目,面向计算机视觉方向的初学者与进阶开发者,解决OCR前处理中因遮挡、模糊或背景干扰导致的文字可读性下降问题。项目包含训练与测…

2026/9/25 3:34:01 阅读更多 →

最新新闻

校园论文选题系统开发实战:Laravel+uniapp+微信小程序

校园论文选题系统开发实战:Laravel+uniapp+微信小程序

毕业论文选题,每年春季都是高校信息部门最头疼的环节。纸质表格传阅、Excel来回汇总、学生线下找老师签字协调,一套流程走下来少说两周,还免不了各种重复和错漏。后来我接手了一个校园团队的项目,用 Thinkphp/Laravel 作为后端、u…

2026/9/25 22:08:45 阅读更多 →
zvec-grep混合搜索原理揭秘:BM25、向量检索与ripgrep如何用RRF融合排名

zvec-grep混合搜索原理揭秘:BM25、向量检索与ripgrep如何用RRF融合排名

zvec-grep混合搜索原理揭秘:BM25、向量检索与ripgrep如何用RRF融合排名 【免费下载链接】zvec-grep Local-first search across your workspace, built for humans and AI agents. 项目地址: https://gitcode.com/gh_mirrors/zv/zvec-grep zvec-grep&#xf…

2026/9/25 22:08:45 阅读更多 →
SpringBoot+Vue 实现办公用品管理系统|计算机毕设源码讲解

SpringBoot+Vue 实现办公用品管理系统|计算机毕设源码讲解

💖💖作者:计算机毕业设计小明哥 💙💙个人简介:曾长期从事计算机专业培训教学,本人也热爱上课教学,语言擅长Java、微信小程序、Python、Golang、安卓Android等,开发项目包…

2026/9/25 22:07:44 阅读更多 →
Python Assert 语句

Python Assert 语句

我们要去搞明白, 到底什么叫做断言。断言是程序里用来坚定地声明或表明某个事实的语句。比如在编一个除法的函数时, 你内心非常确定, 那个除数是不应该等于零的, 所以你就发出了断言, 说明这个除数不是零。断言仅仅只是一个布尔表达式, 它的作用是用来检查某个具体的条件有没有…

2026/9/25 22:07:44 阅读更多 →
阿里云 300万美金加入 Linux 基金会 Alibaba Cloud joins as a Founding Corporate Patron with $3 million

阿里云 300万美金加入 Linux 基金会 Alibaba Cloud joins as a Founding Corporate Patron with $3 million

阿里巴巴云正式加入 Omacom 基金会,成为创始企业赞助人,承诺每年出资 100 万美元,连续三年!这意味着总计 300 万美元的投入,与 DigitalOcean 的赞助金额持平,将全部用于 Omarchy 的开发、维护与推广。 但这…

2026/9/25 22:06:44 阅读更多 →
云服务器怎么搭建python环境变量管理系统

云服务器怎么搭建python环境变量管理系统

要搭建一个系统用来管理环境变量这事儿, 它并不是简简单单就能弄好的, 你首先得具备一定的基础知识储备, 并且还要有一定的编程实际操作经验才行;接下来这儿有一个非常基础的系统框架可以摆在你的面前供你看一看, 这个框架可不是固定不变的死规矩, 它是可以根据你自…

2026/9/25 22:06:44 阅读更多 →

日新闻

AI元人文:从工具使用到思维重构的深度探索

AI元人文:从工具使用到思维重构的深度探索

最近半年我一直在琢磨一件事:AI元人文到底是什么?说白了,就是“用元视角重新审视人与AI的关系”,也在“探索AI如何反向逼着我们发现自己的思考边界”。标题里的“元探索”,在我看就是一层套一层的追问——当你用AI解决…

2026/9/25 0:00:41 阅读更多 →
Python+CNN车牌识别实战:从数据预处理到模型训练与部署

Python+CNN车牌识别实战:从数据预处理到模型训练与部署

简介:基于Python与卷积神经网络的车牌识别项目,面向计算机视觉初学者及智能交通开发者,目标是帮助用户掌握从数据预处理、模型构建到实际部署的完整流程。压缩包共25个文件,包含jpg/png图像样本、py训练脚本、md说明文档、dat数据…

2026/9/25 0:00:41 阅读更多 →
Vim基础操作全攻略:保存退出、模式切换与高频命令实战

Vim基础操作全攻略:保存退出、模式切换与高频命令实战

1. 项目概述1.1 核心需求解析今天聊聊Vim。写这个题目的原因是:几乎每个后端开发者、运维人员、数据工程师某天都会遇到一个场景——深夜加班,服务器登录界面只有黑底白字,编辑器只有vi/vim,你必须在五分钟内完成一次配置修改并保…

2026/9/25 0:00:41 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/25 19:27:14 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/25 11:15:26 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/25 20:29:09 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/25 20:29:43 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/25 20:29:31 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/25 19:27:26 阅读更多 →