yii2 不支持 oss 直传,因直传要求前端直接上传至 oss,后端仅签发 sts 临时凭证或生成 policy 签名;ossclient::putobject() 是服务端同步上传,违背直传本质,且易导致 php 内存溢出或超时。

Yii2 本身不支持 OSS 直传,所谓“直传”必须绕过后端服务器,由前端直接上传到 OSS —— 后端只负责签发临时凭证(STS Token)和生成签名 URL。图片裁剪则分两种:服务端裁剪(用 PHP 处理后再上传)和客户端裁剪(Canvas 压缩/裁剪后转为 base64 或 Blob,再传给后端或直传)。混用时容易出错,关键在路径选择和数据形态转换。
为什么不能直接用 OssClient::putObject() 做直传
因为 putObject() 是服务端 SDK 的同步上传方法,它把文件从 PHP 进程内存或本地磁盘读取后,再发往 OSS。这既不是“直传”,也无法规避用户上传大文件时压垮 PHP 内存或超时的问题。真正的直传要求浏览器(前端)拿到 policy、signature 和 accessKeyId 后,用 POST 直接向 OSS endpoint 提交,PHP 不参与文件流传输。
- 直传必须用阿里云的
PostObject接口,不是PutObject - 后端只需提供 STS 临时 token(推荐)或表单签名(简单但权限难控)
-
OssClient在直传场景里只用来生成签名,不用于上传文件本体
如何让 Yii2 安全签发直传凭证(STS 方案)
硬编码 accessKeyId 和 accessKeySecret 到前端是严重安全漏洞。正确做法是 Yii2 调用阿里云 RAM/STS API 获取临时凭证,返回给前端用于构造直传请求。需提前在 RAM 控制台创建角色并授权 AliyunOSSFullAccess 或最小权限策略。
- 安装阿里云 PHP SDK:
composer require aliyuncs/aliyun-openapi-php-sdk - 配置 STS endpoint(如
https://sts.cn-hangzhou.aliyuncs.com),不是 OSS endpoint - Yii2 控制器中调用
AssumeRoleRequest,返回AccessKeyId、AccessKeySecret、SecurityToken和过期时间 - 前端用这三元组 +
policy(JSON 描述允许上传的bucket、key前缀、content-length-range等)生成签名
前端裁剪后怎么传给 OSS(base64 → Blob → 直传)
很多项目卡在「裁剪完得到 dataURL,却不知道怎么塞进直传表单」。核心问题是:OSS PostObject 只接受 File 或 Blob 类型的 file 字段,不接受 base64 字符串。必须做两步转换:
- 用
dataURLtoBlob()把canvas.toDataURL()结果转成Blob - 用
new File([blob], filename, {type: 'image/jpeg'})包装成File对象(否则部分浏览器无法识别 MIME) - 把这个
File对象 append 到FormData,字段名必须是file(OSS 要求) - 注意:直传表单里的
key字段值要和你生成policy时声明的一致,比如images/${filename}
示例片段:
const blob = dataURLtoBlob(croppedDataURL);
const file = new File([blob], 'avatar.jpg', { type: 'image/jpeg' });
const formData = new FormData();
formData.append('key', `images/${Date.now()}.jpg`);
formData.append('policy', policy);
formData.append('OSSAccessKeyId', accessKeyId);
formData.append('signature', signature);
formData.append('success_action_status', '201');
formData.append('file', file); // ← 这个 file 必须是 File 实例
fetch('https://your-bucket.oss-cn-hangzhou.aliyuncs.com', { method: 'POST', body: formData });
OSS 图片服务裁剪(不走 PHP,纯 URL 参数)
如果只是等比缩放、裁切、加水印,完全没必要在 PHP 里用 GD 或 Imagick 处理——OSS 自带图片处理服务(IMG),只要上传原始图,访问时加参数即可。但要注意两个前提:
- Bucket 所在 region 必须启用图片处理(控制台开启),且使用图片服务专用 endpoint,如
oss-cn-hangzhou-internal.aliyuncs.com→img-cn-hangzhou.aliyuncs.com - 访问域名必须是
bucketname.img-cn-hangzhou.aliyuncs.com,不是bucketname.oss-cn-hangzhou.aliyuncs.com - 参数写法严格:
@50w_50h_1e_1c表示等比缩放到宽高都不超 50px,/crop,w_200,h_200,x_10,y_10表示从 (10,10) 开始裁 200×200 区域
常见坑:putObject() 上传的文件默认不开启 IMG 处理,必须确保上传时没禁用,且 URL 构造无拼写错误(比如把 /resize,w_300 写成 /resize_w_300 就会 404)。
真正麻烦的不是代码量,而是权限链路(RAM 角色 → STS → 前端表单)、数据形态转换(base64 → Blob → File)、以及 OSS endpoint 和 IMG endpoint 的混用。这三个点任一出错,都会表现为 403、400 或图片无法显示。调试时优先检查浏览器 Network 面板里直传请求的 Form Data 和 Response Headers,而不是翻 Yii2 日志。











