睿诚科技协会

iOS如何获取网络图片大小?

通过 HTTP 请求头获取(推荐,高效)

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

iOS如何获取网络图片大小?-图1
(图片来源网络,侵删)

优点:

  • 高效:只获取头部信息,不下载图片数据,节省流量和内存。
  • 快速:请求的数据量极小,响应速度非常快。

缺点:

  • 服务器支持:要求目标服务器必须支持 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)")
    }
}

下载图片后获取(不推荐,仅作为备选)

如果方法一因为服务器不支持等原因失败,你只能先完整下载图片,然后根据下载到的数据来计算大小。

优点:

iOS如何获取网络图片大小?-图2
(图片来源网络,侵删)
  • 通用:只要图片能被下载,这个方法就有效。

缺点:

  • 低效:必须下载完整的图片文件,会消耗大量流量和内存,特别是对于大图。
  • 缓慢:下载过程需要时间,获取大小的时机延后。

实现代码 (使用 UIImageViewsd_setImageKingfisher)

如果你已经在使用像 SDWebImageKingfisher 这样的第三方图片加载库,它们在图片下载完成后会提供回调,可以非常方便地获取到图片数据。

使用 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 的示例:

iOS如何获取网络图片大小?-图3
(图片来源网络,侵删)
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) ,等于图片文件大小
速度 ,取决于图片下载速度
可靠性 依赖服务器支持 HEADContent-Length ,只要能下载图片就有效
适用场景 绝大多数场景,特别是需要预判图片大小、列表展示等 作为备选方案,或当你同时需要图片内容时

最佳实践:

  1. 首选方法一:在任何需要获取网络图片大小的场景下,首先尝试使用 HTTP HEAD 请求,这是最专业、最高效的做法。
  2. 处理失败情况:如果方法一失败(服务器返回错误或没有 Content-Length),再根据你的业务需求决定是否降级到方法二。
  3. 单位转换:获取到字节(bytes)后,通常需要将其转换为更易读的 KB 或 MB 进行展示。1 KB = 1024 Bytes
分享:
扫描分享到社交APP
上一篇
下一篇