应使用upyun api v2(非uss),通过upyun/upyun v3+ sdk上传,路径以/开头,二进制读取文件并设正确content-type;大音频需手动分片上传,避免超时和损坏。

PHP上传音频到又拍云前,先确认你用的是USS还是UPYUN新API
又拍云目前主推的是 UPYUN API v2(基于 OAuth2 认证),老的 USS(又拍云存储服务)SDK 已停止维护。如果你还在用 upyun-sdk-php 1.x 或手动拼接 USS 签名,大概率会返回 401 Unauthorized 或 400 Bad Request —— 这不是代码写错了,是认证方式过时了。
实操建议:
- 删掉旧版
upyun-sdk-php,改用官方维护的upyun/upyun(v3+,支持 v2 API) - 在又拍云控制台「服务管理 → API 密钥」里生成一对
operator和password,别用主账号密码 - 音频文件路径必须以
/开头(如/audio/2024/test.mp3),否则上传会静默失败或返回400
用 upyun/upyun 包上传音频的最小可行代码
安装依赖:composer require upyun/upyun。注意它依赖 guzzlehttp/guzzle,PHP 版本需 ≥7.4。
关键点不是“怎么传”,而是“怎么避免被截断或损坏”:
- 音频文件要以二进制方式读取,
file_get_contents($tmp_file)最稳妥;别用fopen+fread手动分块,容易漏字节 -
putFile()第二个参数必须是原始二进制内容(string),不是文件路径 - 设置
Content-Type很重要:MP3 用audio/mpeg,WAV 用audio/wav,否则又拍云可能不识别格式,导致 CDN 不支持 Range 请求
$client = new \Upyun\Upyun('your-bucket', 'operator', 'password');
$localPath = $_FILES['audio']['tmp_name'];
$content = file_get_contents($localPath);
$remotePath = '/audio/' . uniqid() . '.mp3';
try {
$client->putFile($remotePath, $content, [
'Content-Type' => 'audio/mpeg',
'x-upyun-meta-audio-duration' => '120', // 可选,自定义元数据
]);
echo json_encode(['url' => 'https://your-bucket.b0.upaiyun.com' . $remotePath]);
} catch (\Upyun\UpyunException $e) {
error_log('Upyun upload failed: ' . $e->getMessage());
http_response_code(500);
}
上传大音频(>50MB)必须分片,但 PHP SDK 不自动处理
upyun/upyun 的 putFile() 是单次 HTTP PUT,超时或网络抖动会导致整个上传失败。又拍云对单次请求体大小没硬限制,但 PHP 默认 max_execution_time=30、post_max_size=8M,上传 100MB 音频基本必挂。
正确做法是前端分片 + 后端合并,或改用又拍云的 Multipart Upload 接口(非 SDK 封装):
- 先调
POST /{bucket}/?upload获取upload-id - 每个分片用
PUT /{bucket}/{key}?part-number=N&upload-id=xxx上传 - 最后用
POST /{bucket}/{key}?upload-id=xxx提交合并清单 - PHP 里用
curl或GuzzleHttp\Client手写,别指望 SDK 自动做
注意:分片上传的每个 part 必须 ≥5MB(除最后一片),且不能乱序提交;Content-MD5 头建议带上,校验更稳。
常见音频上传失败原因和对应检查项
遇到 400 Bad Request 别急着重试,先看响应 body 里的 message 字段(SDK 会抛出异常,$e->getMessage() 就是它):
-
invalid bucket name:检查 bucket 名是否全小写、只含字母数字和短横线,且已在控制台创建 -
permission denied:operator 权限不足,确认该 operator 已绑定对应 bucket,且有write权限 -
file type not allowed:不是后缀问题,是又拍云策略里禁用了audio/*MIME 类型,去「服务管理 → 空间设置 → 文件类型白名单」加进去 - 上传后播放杂音或卡顿:大概率是
Content-Type设错,或文件读取时被 PHP 的default_charset或输出缓冲污染(确保上传逻辑前没 echo/print)
音频这种二进制敏感内容,最易被忽略的是 PHP 的输出缓冲和字符编码干扰 —— 上传前加一句 ob_end_clean();,能避开不少诡异问题。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











