15-19.【HTTP】上传大文件或流式数据时,iOS 如何优化?

3 阅读2分钟

1️⃣ 核心问题

上传大文件在 iOS 上主要面临以下挑战:

  1. 内存占用高

    • 如果一次性把整个文件读入内存,会占用大量 RAM,可能导致崩溃。
  2. 网络不稳定 / 中断

    • 长时间上传容易因为网络波动中断,导致上传失败。
  3. 上传速度慢

    • TCP 连接受限于带宽、延迟、队头阻塞等因素。
  4. 后台上传需求

    • 有些文件需要在 app 被挂起或后台时继续上传。

2️⃣ iOS 优化策略

(1) 分块上传 / Chunked Upload

  • 原理:将大文件拆分成小块(例如 1MB/5MB),逐块上传。

  • 优点

    • 内存占用小
    • 可实现断点续传
  • 实现方式

    • URLSessionUploadTask + InputStream 或自定义请求体。
    • 服务器端返回每块上传结果,客户端记录已上传块。
let fileURL = URL(fileURLWithPath: "largefile.mp4")
let request = URLRequest(url: uploadURL)
let task = URLSession.shared.uploadTask(with: request, fromFile: fileURL)
task.resume()

对于超大文件,可用 InputStream 分块读取,而不是 Data(contentsOf:) 全部读入。


(2) 流式上传(Stream Upload)

  • 原理:使用 InputStreamURLSessionStreamTask 将文件流式发送,不一次性加载整个文件。

  • 优势

    • 内存占用极低
    • 支持无限大文件上传
  • 示例

var request = URLRequest(url: uploadURL)
request.httpMethod = "POST"
let stream = InputStream(url: fileURL)
request.httpBodyStream = stream

let task = URLSession.shared.uploadTask(withStreamedRequest: request)
task.resume()

(3) 后台上传任务(Background Upload)

  • 原理:iOS 提供后台 URLSessionConfiguration.background 上传任务,即使 App 被挂起或退出,系统仍会完成上传。
  • 实现方式
let config = URLSessionConfiguration.background(withIdentifier: "com.example.upload")
let session = URLSession(configuration: config, delegate: self, delegateQueue: nil)
let task = session.uploadTask(with: request, fromFile: fileURL)
task.resume()
  • 优势

    • 系统调度,支持网络恢复
    • 避免 App 被杀掉时中断上传

(4) 断点续传 / Range 上传

  • 原理:记录每次上传成功的文件偏移量,下次只上传未完成部分。

  • 实现方式

    • 服务器支持 Content-Range / Range 请求
    • 客户端在网络中断时重试,从上次位置继续上传

(5) 压缩 / 优化文件

  • 对图片、视频等可压缩文件,先在本地压缩,再上传,减少带宽和上传时间。

  • 常用工具:

    • 图片:UIImageJPEGRepresentation / CGImageDestination
    • 视频:AVAssetExportSession

(6) 使用 HTTP/2 或 QUIC

  • HTTP/2 支持多路复用,可并行上传多个小块,避免队头阻塞。
  • iOS 默认 URLSession 支持 HTTP/2。
  • 对 HTTP/3(QUIC),在 iOS16+ 可以使用更低延迟的 UDP 长连接上传。

3️⃣ 总结建议

优化策略优点iOS 实践方法
分块上传 / Chunked Upload内存小,可断点续传uploadTask + InputStream
流式上传内存极低,适合超大文件uploadTask(withStreamedRequest:)
后台上传任务系统调度,App 被挂起也可上传background URLSession
断点续传 / Range 上传避免重复上传Content-Range Header
文件压缩减少带宽,提升速度UIImageJPEGRepresentation / AVAssetExportSession
HTTP/2 / HTTP/3 优化多路复用、减少延迟URLSession 自动使用 HTTP/2 / HTTP/3

💡 面试加分点

  • 能区分 流式 vs 分块 vs 一次性上传 的场景。
  • 了解 后台上传 + 断点续传 的 iOS 实践。
  • 理解 TCP / HTTP/2 对上传性能的影响。