You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel中用预签名URL上传S3遇SignatureDoesNotMatch错误

解决S3预签名URL上传时的SignatureDoesNotMatch错误

以下是导致签名不匹配的几个关键问题及修复方案:

1. Content-Type不匹配或格式错误

预签名URL生成时如果未指定Content-Type,实际请求中新增的Content-Type会导致签名校验失败。同时你设置的'MP4'不是标准MIME类型,正确值应为'video/mp4'。

修复:

生成预签名命令时明确指定Content-Type,确保和请求时一致:

$cmd = $s3Client->getCommand('PutObject', [
    'Bucket' => config('filesystems.disks.s3.bucket'),
    'Key' => $path,
    'Content-Type' => 'video/mp4' // 添加此行,与请求保持一致
]);

同时修正curl请求的headers:

$headers = [
    'Content-Type: video/mp4', // 改为标准MIME类型格式
];

2. CURL参数混用错误

同时使用CURLOPT_PUT和CURLOPT_POSTFIELDS会导致请求格式异常,对于PUT上传,应使用文件流方式传递内容,既保证请求正确性又避免大文件内存溢出问题。

修复:

替换curl相关代码为:

$ch = curl_init($presignedUrl);
// 启用上传模式
curl_setopt($ch, CURLOPT_UPLOAD, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
// 打开文件流
$fileHandle = fopen($file, 'r');
curl_setopt($ch, CURLOPT_INFILE, $fileHandle);
// 使用文件实际大小,避免二进制文件长度计算错误
curl_setopt($ch, CURLOPT_INFILESIZE, filesize($file));

$response = curl_exec($ch);
// 关闭文件流
fclose($fileHandle);
curl_close($ch);

3. Content-Length计算错误

strlen($fileContents)不适用于MP4这类二进制文件,会导致长度计算不准确,进而触发签名校验失败。改用filesize($file)直接获取文件实际大小即可解决。

额外检查项

  • 确认AWS凭证(key/secret)和区域配置完全正确,无拼写错误
  • 确保生成预签名URL的$path与实际上传的对象Key完全一致,S3的Key区分大小写

内容的提问来源于stack exchange,提问作者vinita darji

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 07:00:20