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

SwiftUI通过UIImagePickerController上传视频到Firebase Storage报-13000错

SwiftUI项目上传视频到Firebase Storage报错-13000解决方案

问题描述

在SwiftUI项目中实现选中视频后上传到Firebase Storage的功能,核心实现代码如下:

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        
        guard let uid = Firebase.Auth.auth().currentUser?.uid else {return}
        let ref = Storage.storage().reference(withPath: uid)

        if let url = info[.mediaURL] as? URL {
                ref.putFile(from: url, metadata: nil) { metadata, error in
                    if error != nil{
                        print(error)
                        return
                    }else{
                        print("Succes")
                    }
                }
        }
        picker.dismiss(animated: true)
    }

运行代码执行上传时,抛出如下错误:

Error Domain=FIRStorageErrorDomain Code=-13000 "发生未知错误,请检查服务端返回结果"
错误附带信息:

  • 存储桶:skidays-d2cc1.appspot.com
  • 失败任务类型:后台上传任务
  • 错误域:NSURLErrorDomain
  • 对应请求地址:Firebase Storage分块上传接口
  • 响应错误码:-1

核心诱因

这个错误90%以上的场景是代码逻辑问题导致的:

  • 发起putFile上传请求后,代码立刻执行了picker.dismiss关闭图片选择器。UIImagePickerController返回的mediaURL是临时目录下的文件URL,选择器被销毁后系统会自动回收该临时路径下的文件,Firebase的后台上传任务还没来得及读取文件内容,源文件就已经被删除,直接触发上传失败。
  • 剩余小概率诱因包括:Firebase Storage安全规则未给当前登录用户开放对应路径的写入权限、测试网络拦截了Firebase存储请求、Info.plist未配置必要的网络访问权限。

修复方案

  1. 调整代码执行逻辑,不要在发起上传后立刻关闭选择器,先将选择器返回的临时视频文件拷贝到应用沙盒的持久化临时路径,再用沙盒内的文件URL发起上传,等上传回调触发后再关闭选择器、清理临时文件。
    修复后的代码参考:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
    // 未登录状态直接关闭选择器
    guard let uid = Auth.auth().currentUser?.uid else {
        picker.dismiss(animated: true)
        return
    }
    // 未获取到媒体URL直接关闭选择器
    guard let mediaURL = info[.mediaURL] as? URL else {
        picker.dismiss(animated: true)
        return
    }
    
    // 生成沙盒内的持久化临时路径
    let sandboxTempURL = FileManager.default.temporaryDirectory
        .appendingPathComponent(UUID().uuidString)
        .appendingPathExtension("mov")
    
    do {
        // 路径下存在旧文件先删除
        if FileManager.default.fileExists(atPath: sandboxTempURL.path) {
            try FileManager.default.removeItem(at: sandboxTempURL)
        }
        // 将选择器返回的临时文件拷贝到沙盒路径
        try FileManager.default.copyItem(at: mediaURL, to: sandboxTempURL)
        
        // 按用户uid+文件名生成存储路径,避免同一路径文件覆盖
        let storageRef = Storage.storage().reference()
            .child(uid)
            .child(sandboxTempURL.lastPathComponent)
        
        // 用沙盒路径发起上传
        storageRef.putFile(from: sandboxTempURL, metadata: nil) { [weak self] _, error in
            // 无论上传成功失败,最后都关闭选择器、清理沙盒临时文件
            defer {
                picker.dismiss(animated: true)
                try? FileManager.default.removeItem(at: sandboxTempURL)
            }
            
            if let error = error {
                print("上传失败:\(error.localizedDescription)")
                return
            }
            print("上传成功")
        }
    } catch {
        print("文件预处理失败:\(error.localizedDescription)")
        picker.dismiss(animated: true)
    }
}
  1. 检查Firebase Storage安全规则,确认当前登录用户有目标路径的写入权限,测试阶段可以先用如下规则验证逻辑是否正常:
rules_version = '2';
service firebase.storage {
  match /b/{bucket}/o {
    match /{userId}/{allPaths=**} {
      allow read, write: if request.auth != null && request.auth.uid == userId;
    }
  }
}
  1. 确认测试设备网络可以正常访问Firebase服务,Info.plist中已配置网络访问权限,没有代理、防火墙拦截存储接口请求。

内容的提问来源于stack exchange,提问作者Michał Michalik

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 04:09:31