通过 HTTP 请求头获取(推荐,高效)
这是最推荐、最高效的方法,你不需要下载图片的完整内容,只需要发送一个 HTTP HEAD 请求到图片的 URL,HEAD 请求会返回和 GET 请求一样的响应头,但不包含响应体(也就是图片内容本身),响应头中的 Content-Length 字段直接告诉了你这个文件的大小(以字节为单位)。

优点:
- 高效:只获取头部信息,不下载图片数据,节省流量和内存。
- 快速:请求的数据量极小,响应速度非常快。
缺点:
- 服务器支持:要求目标服务器必须支持 HEAD 请求,并且正确返回
Content-Length,绝大多数主流服务器都支持。
实现代码 (使用 URLSession)
import UIKit
// 定义一个闭包类型,用于异步返回结果
typealias ImageSizeCompletion = (Result<Int, Error>) -> Void
// MARK: - 通过 HTTP 头部获取图片大小
func getImageSizeFromURL(urlString: String, completion: @escaping ImageSizeCompletion) {
guard let url = URL(string: urlString) else {
completion(.failure(NSError(domain: "Invalid URL", code: -1, userInfo: nil)))
return
}
// 创建一个 URLSessionDataTask
var request = URLRequest(url: url)
request.httpMethod = "HEAD" // 关键:使用 HEAD 方法
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
if let error = error {
// 请求失败
completion(.failure(error))
return
}
// 检查响应是否为 HTTPURLResponse 并且状态码是 2xx
guard let httpResponse = response as? HTTPURLResponse,
(200...299).contains(httpResponse.statusCode) else {
completion(.failure(NSError(domain: "Invalid HTTP Response", code: -2, userInfo: nil)))
return
}
// 从响应头中获取 Content-Length
if let contentLength = httpResponse.value(forHTTPHeaderField: "Content-Length") {
// 将 String 转换为 Int
if let sizeInBytes = Int(contentLength) {
// 返回成功结果,单位是字节
completion(.success(sizeInBytes))
} else {
completion(.failure(NSError(domain: "Invalid Content-Length value", code: -3, userInfo: nil)))
}
} else {
// 服务器没有返回 Content-Length
completion(.failure(NSError(domain: "Content-Length header not found", code: -4, userInfo: nil)))
}
}
task.resume()
}
// MARK: - 使用示例
let imageUrl = "https://img.zcool.cn/community/0312e358c71e87a801211d5368a5f5.jpg@1280w_1l_2o_100sh.jpg"
getImageSizeFromURL(urlString: imageUrl) { result in
switch result {
case .success(let sizeInBytes):
// 将字节转换为 KB 或 MB
let sizeInKB = Double(sizeInBytes) / 1024.0
let sizeInMB = sizeInKB / 1024.0
print("图片大小: \(sizeInBytes) 字节")
print("图片大小: \(String(format: "%.2f", sizeInKB)) KB")
print("图片大小: \(String(format: "%.2f", sizeInMB)) MB")
// 在主线程更新 UI
DispatchQueue.main.async {
// 更新一个 Label
// self.sizeLabel.text = "图片大小: \(String(format: "%.2f", sizeInMB)) MB"
}
case .failure(let error):
print("获取图片大小失败: \(error.localizedDescription)")
}
}
下载图片后获取(不推荐,仅作为备选)
如果方法一因为服务器不支持等原因失败,你只能先完整下载图片,然后根据下载到的数据来计算大小。
优点:

- 通用:只要图片能被下载,这个方法就有效。
缺点:
- 低效:必须下载完整的图片文件,会消耗大量流量和内存,特别是对于大图。
- 缓慢:下载过程需要时间,获取大小的时机延后。
实现代码 (使用 UIImageView 的 sd_setImage 或 Kingfisher)
如果你已经在使用像 SDWebImage 或 Kingfisher 这样的第三方图片加载库,它们在图片下载完成后会提供回调,可以非常方便地获取到图片数据。
使用 SDWebImage 的示例:
import UIKit
import SDWebImage
let imageView = UIImageView()
let imageUrl = "https://img.zcool.cn/community/0312e358c71e87a801211d5368a5f5.jpg@1280w_1l_2o_100sh.jpg"
imageView.sd_setImage(with: URL(string: imageUrl)) { (image, data, error, cacheType, url) in
if let error = error {
print("图片下载失败: \(error.localizedDescription)")
return
}
// data 就是下载到的图片数据
if let imageData = data {
let sizeInBytes = imageData.count
let sizeInKB = Double(sizeInBytes) / 1024.0
let sizeInMB = sizeInKB / 1024.0
print("图片大小: \(sizeInBytes) 字节")
print("图片大小: \(String(format: "%.2f", sizeInKB)) KB")
print("图片大小: \(String(format: "%.2f", sizeInMB)) MB")
// 在主线程更新 UI
DispatchQueue.main.async {
// self.sizeLabel.text = "图片大小: \(String(format: "%.2f", sizeInMB)) MB"
}
}
}
使用原生 URLSession 的示例:

import UIKit
func downloadAndGetImageSize(urlString: String) {
guard let url = URL(string: urlString) else { return }
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
if let error = error {
print("下载失败: \(error.localizedDescription)")
return
}
guard let imageData = data else {
print("未获取到图片数据")
return
}
let sizeInBytes = imageData.count
print("图片大小: \(sizeInBytes) 字节")
}
task.resume()
}
总结与对比
| 特性 | 方法一 (HTTP HEAD) | 方法二 (下载后获取) |
|---|---|---|
| 效率 | 极高,只请求头部 | 低,必须下载完整文件 |
| 流量消耗 | 极低 (几 KB) | 高,等于图片文件大小 |
| 速度 | 快 | 慢,取决于图片下载速度 |
| 可靠性 | 依赖服务器支持 HEAD 和 Content-Length |
高,只要能下载图片就有效 |
| 适用场景 | 绝大多数场景,特别是需要预判图片大小、列表展示等 | 作为备选方案,或当你同时需要图片内容时 |
最佳实践:
- 首选方法一:在任何需要获取网络图片大小的场景下,首先尝试使用 HTTP HEAD 请求,这是最专业、最高效的做法。
- 处理失败情况:如果方法一失败(服务器返回错误或没有
Content-Length),再根据你的业务需求决定是否降级到方法二。 - 单位转换:获取到字节(bytes)后,通常需要将其转换为更易读的 KB 或 MB 进行展示。
1 KB = 1024 Bytes。
