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

Swift通过可恢复API上传视频到Vimeo第二步报Content-Type错误如何解决

问题根因

你的请求报错核心原因是错误使用了Alamofire的multipart表单上传接口,直接违反了Vimeo可恢复上传的tus协议规范:

  1. tus协议要求第二步PATCH请求的请求体是纯二进制视频流,对应Content-Type必须为你手动设置的application/offset+octet-stream。但调用AF.upload(multipartFormData:)方法时,Alamofire会自动将Content-Type重写为multipart/form-data; boundary=随机边界值,直接覆盖你手动配置的头字段,服务端收到请求后校验Content-Type不匹配,就会返回对应错误。
  2. 你当前的实现还有两个额外隐患:
    • multipart场景下的withName参数是用来指定表单字段名的,纯二进制流上传不需要这个配置,强行加会在二进制流前后插入表单分隔符,导致服务端解析视频内容失败。
    • 用Data(contentsOf:)把整个视频文件全量加载进内存,上传大体积视频时会触发内存暴涨,很容易被系统直接杀死进程。
修复代码

直接使用Alamofire的文件上传接口,不要走multipart逻辑,传入本地视频URL即可,Alamofire不会篡改你预设的请求头,同时会以分片读文件的方式上传,避免内存溢出:

private func uploadVideoToVimeo(uploadLink:String) {
    guard let uploadUrl = URL(string: uploadLink) else { return }
    
    let headers: HTTPHeaders = [ 
        "Tus-Resumable":"1.0.0",
        "Upload-Offset": "0",
        "Content-Type": "application/offset+octet-stream",
        "Accept":"application/vnd.vimeo.*+json;version=3.4"
    ]

    var request = URLRequest(url: uploadUrl)
    request.headers = headers
    request.method = .patch
    
    // 直接传入本地文件URL上传,不要构造multipart表单
    AF.upload(self.videoLocalURL, with: request)
        .responseString { response in
            switch response.result {
            case .success(let data):
                print("上传响应: \(response)")
                // 后续断点续传可从响应头的Upload-Offset字段获取当前上传进度
            case let .failure(error):
                print("上传错误: \(error)")
            }
        }
}
后续注意事项
  • 实现完整可恢复上传逻辑时,不要硬编码Upload-Offset为0,每次发起续传请求前需要先向上传地址发送HEAD请求,获取服务端实际存储的文件偏移量,再从对应位置开始上传剩余内容,避免出现内容覆盖、上传损坏的问题。
  • 如果需要监听上传进度,可以给上传请求追加uploadProgress回调,不要手动计算分片大小,Alamofire底层会自动处理流读取逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 03:39:25