1️⃣ 核心问题
上传大文件在 iOS 上主要面临以下挑战:
-
内存占用高
- 如果一次性把整个文件读入内存,会占用大量 RAM,可能导致崩溃。
-
网络不稳定 / 中断
- 长时间上传容易因为网络波动中断,导致上传失败。
-
上传速度慢
- TCP 连接受限于带宽、延迟、队头阻塞等因素。
-
后台上传需求
- 有些文件需要在 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)
-
原理:使用
InputStream或URLSessionStreamTask将文件流式发送,不一次性加载整个文件。 -
优势:
- 内存占用极低
- 支持无限大文件上传
-
示例:
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 对上传性能的影响。