必须确认七牛云AccessKey和SecretKey正确,否则返回401或invalid token;上传音频需用putFile()或resumableUpload()(>2GB时),并显式指定mime类型,上传后校验Content-Type和可播放性。

上传前必须确认七牛云的 AccessKey 和 SecretKey 是否正确
七牛云 SDK 需要有效的密钥对才能签名上传请求,如果 AccessKey 或 SecretKey 错误,会直接返回 401 Unauthorized 或 invalid token 错误。建议从七牛云控制台「个人中心 → 密钥管理」复制,不要手动输入或从旧文档里拷贝。
常见坑点:
- 用错环境密钥(测试环境用了生产密钥,或反之)
- 密钥末尾有空格(复制时容易带入)
- SecretKey 被当成 AccessKey 传入(两者长度和字符集不同,但错误传参不会报语法错,只会在签名阶段失败)
用 qiniu/php-sdk 的 putFile() 直接上传音频文件
不用自己拼 token、发 HTTP 请求,SDK 封装了完整流程。关键是要先生成 UploadToken,再调用 putFile()。
示例代码片段(省略异常处理,仅展示主干):
立即学习“PHP免费学习笔记(深入)”;
$accessKey = 'your_access_key';
$secretKey = 'your_secret_key';
$bucket = 'your-audio-bucket';
$key = 'audio/' . uniqid() . '.mp3'; // 上传后的文件名,建议带路径前缀防冲突
<p>$auth = new \Qiniu\Auth($accessKey, $secretKey);
$upToken = $auth->uploadToken($bucket);</p><p>$config = new \Qiniu\Config();
$bucketManager = new \Qiniu\Storage\BucketManager($auth, $config);
$uploadMgr = new \Qiniu\Storage\UploadManager($config);</p><p>// 假设 $_FILES['audio']['tmp_name'] 是上传的音频临时文件
list($ret, $err) = $uploadMgr->putFile($upToken, $key, $_FILES['audio']['tmp_name']);
if ($err !== null) {
// 处理错误,比如:$err->message() 可能是 "file not exists" 或 "invalid file size"
}
注意:
-
putFile()第三个参数必须是服务器上的真实路径($_FILES的tmp_name),不能是 URL 或 base64 字符串 - 音频文件大小受 PHP
upload_max_filesize和post_max_size限制,需提前检查ini_get('upload_max_filesize') - 七牛默认单文件上限 4GB,但 PHP 默认只支持到 2GB(
int溢出),大音频建议分片上传(见下一条)
大音频(>2GB)必须用 resumableUpload() 分片上传
PHP 的 fopen() 和 filesize() 在 32 位系统或某些 SAPI 下对 >2GB 文件会返回负数或 0,导致 putFile() 签名失败或上传中断。七牛 SDK 提供了 resumableUpload() 来规避这个问题。
使用要点:
- 需启用
cURL扩展(分片依赖curl多段 POST) - 临时文件不能被删除或移动,否则分片读取失败
- 建议设置
partSize参数为4 * 1024 * 1024(4MB),避免小分片过多拖慢速度 - 上传成功后,
$ret['key']是最终可访问的文件名,$ret['hash']是文件 etag(可用于去重)
上传后记得校验 Content-Type 和音频可播放性
七牛不会自动识别音频 MIME 类型,如果上传时没指定,可能被设为 application/octet-stream,导致浏览器无法内联播放。解决方法是在 putFile() 或 resumableUpload() 的 $params 中显式传 mime:
$params = ['mime' => 'audio/mpeg']; // mp3 // 或 'audio/wav', 'audio/flac', 'audio/ogg' 等 list($ret, $err) = $uploadMgr->putFile($upToken, $key, $filePath, null, $params);
更稳妥的做法是用 finfo_file() 动态探测:
$finfo = finfo_open(FILEINFO_MIME_TYPE); $mimeType = finfo_file($finfo, $_FILES['audio']['tmp_name']); finfo_close($finfo); $params = ['mime' => $mimeType];
上传完成后,别急着返回链接——先用 curl -I 或 SDK 的 stat() 方法查一下 Content-Type 和 Content-Length 是否符合预期。很多“上传成功但打不开”的问题,根源都在这里。



















