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

Swift如何检测zip压缩包内是否包含视频内容?

Swift 检测ZIP压缩包是否包含视频内容实现方案

要实现带视频的ZIP包禁止预览的需求,核心逻辑是读取ZIP包内的文件清单,匹配常见视频文件后缀即可,不需要完整解压ZIP包,性能开销极低。


方案1:使用ZIPFoundation实现(推荐,代码量少)

ZIPFoundation是Swift原生的ZIP处理库,可通过SPM直接集成,实现代码如下:

import ZIPFoundation

// 传入zip文件的本地URL,返回是否包含视频文件
func isZipContainsVideo(zipPath: URL) -> Bool {
    // 可根据业务需求扩展需要拦截的视频后缀
    let videoSuffixSet: Set<String> = ["mp4", "mov", "avi", "mkv", "flv", "wmv", "m4v", "webm", "mpeg", "mpg"]
    // 只读模式打开ZIP包,不会执行解压
    guard let zipArchive = Archive(url: zipPath, accessMode: .read) else {
        return false
    }
    // 遍历ZIP内所有文件条目
    for entry in zipArchive where entry.type == .file {
        let fileSuffix = entry.path.lowercased().components(separatedBy: ".").last ?? ""
        if videoSuffixSet.contains(fileSuffix) {
            return true
        }
    }
    return false
}

调用逻辑:在初始化UIDocumentInteractionController触发预览前,先调用上述方法,若返回true则直接拦截预览,返回false再执行预览逻辑即可。


方案2:使用系统Compression框架实现(无第三方依赖)

如果不想引入外部依赖,可以直接解析ZIP的二进制结构读取文件清单,实现代码如下:

import Foundation
import Compression

func isZipContainsVideoSystemImpl(zipPath: URL) -> Bool {
    let videoSuffixSet: Set<String> = ["mp4", "mov", "avi", "mkv", "flv", "wmv", "m4v", "webm", "mpeg", "mpg"]
    guard let zipData = try? Data(contentsOf: zipPath) else {
        return false
    }
    // 定位ZIP中央目录结束标记
    var offset = zipData.count - 22
    let endOfCentralDirSignature: UInt32 = 0x06054b50
    
    while offset >= 0 {
        let signature = zipData.withUnsafeBytes { $0.load(fromByteOffset: offset, as: UInt32.self) }
        if signature == endOfCentralDirSignature {
            // 读取中央目录起始偏移
            let centralDirOffset = zipData.withUnsafeBytes { $0.load(fromByteOffset: offset + 16, as: UInt32.self) }
            let centralDirSize = zipData.withUnsafeBytes { $0.load(fromByteOffset: offset + 12, as: UInt32.self) }
            var currentOffset = Int(centralDirOffset)
            let centralDirEnd = currentOffset + Int(centralDirSize)
            let centralFileHeaderSig: UInt32 = 0x02014b50
            
            while currentOffset < centralDirEnd {
                let headerSig = zipData.withUnsafeBytes { $0.load(fromByteOffset: currentOffset, as: UInt32.self) }
                guard headerSig == centralFileHeaderSig else { break }
                let fileNameLength = zipData.withUnsafeBytes { $0.load(fromByteOffset: currentOffset + 28, as: UInt16.self) }
                let extraFieldLength = zipData.withUnsafeBytes { $0.load(fromByteOffset: currentOffset + 30, as: UInt16.self) }
                let commentLength = zipData.withUnsafeBytes { $0.load(fromByteOffset: currentOffset + 32, as: UInt16.self) }
                let fileNameStart = currentOffset + 46
                guard fileNameStart + Int(fileNameLength) <= zipData.count else { break }
                let fileNameData = zipData.subdata(in: fileNameStart..<fileNameStart + Int(fileNameLength))
                if let fileName = String(data: fileNameData, encoding: .utf8)?.lowercased() {
                    let suffix = fileName.components(separatedBy: ".").last ?? ""
                    if videoSuffixSet.contains(suffix) {
                        return true
                    }
                }
                currentOffset += 46 + Int(fileNameLength) + Int(extraFieldLength) + Int(commentLength)
            }
            break
        }
        offset -= 1
    }
    return false
}

注意事项

  • 两种方案都仅读取ZIP的文件头信息,不会解压完整文件,大体积ZIP包也可以快速完成检测
  • 可根据业务场景自行扩展videoSuffixSet集合内的视频后缀,覆盖所有需要拦截的视频格式
  • 检测不包含视频后,再正常调用UIDocumentInteractionController的相关方法实现ZIP预览即可

内容的提问来源于stack exchange,提问作者Sudhi 9135

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.15 18:27:03