webman 不能直接用 minio-php-sdk,因其依赖 guzzle 7.x+ 与 webman 协程 http 客户端底层调度冲突;sdk 的 putobject 默认分块上传且未正确释放资源,导致连接堆积、curl error 56。

Webman 项目直接对接 MinIO 是可行的,但必须绕过官方 SDK 的冗余依赖和自动重试逻辑——否则上传大文件时容易卡死或内存溢出。
为什么 Webman 不能直接用 minio-php-sdk
minio-php-sdk 依赖 guzzlehttp/guzzle 7.x+,而 Webman 默认使用 workerman/http 或 webman/framework 自带的协程 HTTP 客户端,两者底层调度冲突;SDK 内部的 putObject 默认启用分块上传(partSize 固定 5MB),但 Webman 的协程环境未正确释放资源,会导致连接堆积、超时后抛出 cURL error 56: Failure when receiving data from the peer。
- 不要在 Webman 中执行
composer require minio/minio-php-sdk - 避免调用
MinioClient::putObject()直接传 file handle —— 它会尝试读取整个文件进内存 - Webman 的
request()->file()返回的是临时路径,不是流资源,别误当成fopen()句柄
推荐用原生 S3 兼容接口 + Guzzle 协程适配
MinIO 完全兼容 AWS S3 API,Webman 可直接用轻量级 aws/aws-sdk-php(v3.290+)并切换为协程友好的 AsyncAws\S3 或手动构造签名请求。更稳妥的做法是:用 guzzlehttp/guzzle 配合 aws/aws-sdk-php 的 S3Client,但禁用长连接和自动重试:
- 安装时加
--with-deps确保guzzlehttp/psr7版本 ≥ 2.4.0(否则StreamWrapper不兼容协程) - 初始化客户端时传入:
'retries' => 0, 'http' => ['timeout' => 30, 'connect_timeout' => 10] - 上传必须用
putObject的Body参数传file_get_contents($tmpPath)(仅限 ≤ 20MB 小文件)或分片上传逻辑自己写
示例关键代码片段:
Webman 2.2.0版本强化了 TCP/UDP 服务支持,优化路由组管理,并增强异步任务处理能力。结合协程与连接池技术,Webman 能轻松应对高并发场景,适用于网站、接口服务、即时通讯、物联网及游戏开发,兼具高性能、灵活扩展与稳定可靠,是多场景 PHP 服务开发的理想选择。
$s3 = new S3Client([
'version' => 'latest',
'region' => 'us-east-1',
'endpoint' => 'http://minio.example.com:9000',
'credentials' => [
'key' => 'admin',
'secret' => 'your_secure_password',
],
'retries' => 0,
'http' => ['timeout' => 30],
]);
$result = $s3->putObject([
'Bucket' => 'uploads',
'Key' => 'avatar/' . uniqid() . '.jpg',
'Body' => fopen($tmpFile, 'rb'), // 注意:这里必须是真实 resource,不是 string
'ContentType' => 'image/jpeg',
]);
Webman 中处理大文件上传的绕过方案
超过 20MB 的文件,别走 PHP 层中转。MinIO 支持预签名 POST 表单直传(createPresignedPost),让浏览器/APP 直连 MinIO,Webman 只负责签发 token 和校验回调。
- MinIO 必须开启
cors配置,允许你的 Webman 域名跨域 POST 到/<bucket></bucket> - Webman 控制器里调用
$s3->createPresignedPost()返回表单字段,前端用<form></form>提交到 MinIO endpoint - MinIO 不支持回调通知,需在 Webman 接口里用
headObject轮询确认文件是否写入完成(最多 3 次,间隔 500ms) - 上传成功后,MinIO 的 Object Key 就是前端表单里填的
key字段值,无需再从响应体解析
权限与 Bucket 策略容易被忽略的点
Webman 后端代码使用的密钥对,不能是 MinIO 的 root 用户(MINIO_ROOT_USER),必须创建独立 service account 并绑定最小权限策略:
- 策略 JSON 中
Resource字段必须精确到arn:aws:s3:::uploads/*,不能写*,否则 Webman 一旦被 XSS 注入就可能删光所有桶 - MinIO 控制台里新建用户后,导出的
accessKey/secretKey才能用于 Webman,root 凭据只用于初始化 - 如果 Webman 需要列出 bucket 内文件,策略里必须显式包含
s3:ListBucket,且Condition中加上"StringLike": {"s3:prefix": ["uploads/"]}
实际部署时,MinIO 的 /data 目录权限、systemd 服务以非 root 用户运行、以及 Webman 进程对临时上传目录的写权限,三者缺一不可——任一环节权限不对,都会表现为 file not found 或静默失败。










