PHP上传阿里云OSS最稳妥方式是用官方SDK的putObject(传字符串内容)或uploadFile(传本地文件路径),5GB以内用简单上传,超大文件必须用multiUpload分片上传。

直接说结论:PHP上传文件到阿里云OSS,最稳妥的方式是用官方 SDK 的 putObject(字符串)或 uploadFile(本地文件),别手写 HTTP 请求;5 GB 以内用简单上传,超大文件必须走 multiUpload。
怎么选 putObject 还是 uploadFile
两者底层都走 PUT,但参数和适用场景不同:
-
putObject($bucket, $object, $content, $options):传字符串内容,适合小文本、JSON、生成的缩略图二进制流(file_get_contents后直接传) -
uploadFile($bucket, $object, $filePath, $options):传本地磁盘路径,适合用户上传的$_FILES临时文件,SDK 自动分块读取,内存友好 - 误用
putObject传大文件路径(比如把$_FILES['file']['tmp_name']当字符串传)会导致内容错乱,因为 PHP 会把路径字符串当内容发出去,不是读文件 - 如果用
uploadFile,确保$filePath是真实可读的临时文件路径,且没被move_uploaded_file移走或销毁
uploadFile 上传失败常见报错及原因
实际开发中最常卡在这几步:
- 报错
OssException: InvalidArgument: The specified object key is invalid.→$object路径含非法字符(如中文、空格、反斜杠),建议用rawurlencode()处理文件名部分,目录部分保持 ASCII - 报错
OssException: AccessDenied→ RAM 用户缺权限,至少要oss:PutObject;若开了服务端加密(KMS),还得加kms:GenerateDataKey - 报错
OssException: RequestExpired→ 服务器时间严重偏差(>15 分钟),OSS 签名校验失败,用ntpdate -u ntp.aliyun.com校时 - 上传后文件为空或损坏 → 检查
$filePath是否为is_uploaded_file()返回 true,别直接信任$_FILES['x']['tmp_name']
大文件(>100 MB)必须用 multiUpload
简单上传(putObject/uploadFile)虽方便,但不支持断点续传,超大文件容易因网络抖动失败。分片上传才是生产环境标配:
立即学习“PHP免费学习笔记(深入)”;
-
$ossClient->initiateMultipartUpload($bucket, $object)返回uploadId,必须持久化(存 DB 或 Redis),后续所有分片都依赖它 - 每个分片调用
$ossClient->uploadPart($bucket, $object, $uploadId, $partNumber, $filePath, $offset, $length),注意$offset和$length要对齐,不能重叠或跳空 - 最后必须调用
$ossClient->completeMultipartUpload($bucket, $object, $uploadId, $partList),否则碎片残留,按天计费 - 别省事跳过
listParts校验 —— 网络中断后可能部分分片已上传成功,直接complete会丢数据
上传回调(Callback)配置容易漏的关键点
想让 OSS 上传完主动通知你的服务器(比如更新数据库状态),得配 Callback,但很多人卡在签名和字段格式:
- Callback 参数必须是 JSON 字符串,且 base64 编码后塞进
options[OssClient::OSS_CALLBACK],不是直接传数组 - 回调 URL 必须是公网可访问的地址,且响应必须是 JSON 格式,HTTP 状态码 200,否则 OSS 会重试最多 3 次
- 回调 Body 示例:
{"callbackUrl":"https://your-api.com/oss-callback","callbackHost":"your-api.com","callbackBody":"{\"filename\":\"$(object)\",\"size\":\"$(size)\"}"},注意双引号和反斜杠转义 - 服务端收到回调后,必须用 OSS 提供的签名算法验证
X-Oss-Callback-Signature头,否则可能是伪造请求
真正难的不是调哪个函数,而是上传路径怎么设计才利于 CDN 加速、回调怎么防重放、分片失败后如何安全清理 —— 这些细节没处理好,上线后就是半夜告警。



















