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

Swift上传Presigned-URL遇SignatureDoesNotMatch错误求助

解决Swift上传Presigned URL时的SignatureDoesNotMatch错误

已知curl可正常上传但Swift代码报错,核心原因是Swift请求的参数/请求头与生成预签名URL时约定的规则不匹配,以下是具体排查和修复方案:

1. 严格匹配Content-Type

预签名URL生成时若指定了Content-Type,上传请求的Content-Type必须完全一致(包括大小写、附加参数,比如生成时是audio/m4a; charset=utf-8,仅传audio/m4a会导致不匹配)。

  • 若curl未指定Content-Type也能成功,说明预签名URL允许任意类型,可尝试删除Swift代码中的Content-Type设置,让URLSession自动处理;
  • 若必须指定,确保和生成预签名URL时的取值完全一致。

2. 移除URLSession自动添加的额外请求头

URLSession会自动添加Content-Length、Transfer-Encoding、User-Agent等默认头,若这些头不在预签名URL的签名范围内,会触发签名不匹配。可手动清理:

// 移除自动添加的Content-Length和Transfer-Encoding
request.setValue(nil, forHTTPHeaderField: "Content-Length")
request.setValue(nil, forHTTPHeaderField: "Transfer-Encoding")
// 只保留确认需要的请求头(覆盖默认头集合)
request.allHTTPHeaderFields = ["Content-Type": "audio/m4a"]

3. 对比curl与Swift的完整请求内容

通过日志对比两者的请求头,找出差异项并修正:

  • 用curl -v -X PUT -T 你的文件路径 "预签名URL"查看curl的完整请求头;
  • 完善Swift的日志方法,打印所有请求头:
func logRequestDetails(_ request: URLRequest) {
    print("请求方法: \(request.httpMethod ?? "未知")")
    print("请求URL: \(request.url ?? URL(fileURLWithPath: ""))")
    print("请求头: \(request.allHTTPHeaderFields ?? [:])")
}

若Swift请求中存在curl没有的头(如Accept),需在代码中移除这些冗余头。

4. 验证文件一致性与读取方式

  • 确认Swift上传的文件和curl使用的是同一文件,未被其他进程修改;
  • 若怀疑文件读取问题,可尝试先将文件转为Data再上传:
do {
    let fileData = try Data(contentsOf: fileURL)
    let task = URLSession.shared.uploadTask(with: request, from: fileData) { data, response, error in
        // 原有回调逻辑不变
    }
    task.resume()
} catch {
    print("读取文件失败: \(error)")
}

内容的提问来源于stack exchange,提问作者Haziq Nordin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 12:21:22