使用Swift开发一个贝乐虎启蒙App – 读绘本(一)

这是我参与8月更文挑战的第14天,活动详情查看:8月更文挑战

前言

视频和音频播放都已经搞完了,接下来就搞下读绘本吧。

IMG_0243.PNG

抓取接口数据发现,里面有个url字段,url是一个zip链接

截屏2021-08-10 09.21.37.png

用浏览器打开一个链接将其下载下来并解压

WeChat2d3ee7ac04a59276aecb056e17564081.png

通过上面的截图可以看到,里面包含了图片和音频资源,还有一个index.json文件

index.json文件是绘本的信息,包含图片和音频名称、音频时长

截屏2021-08-10 09.38.39.png

读绘本其实就是一张图片配个音频,滑到哪张图片播放哪个音频。所以现在的步骤是:

1、下载zip
2、解压zip
3、处理解压后的包
4、播放

下载zip

下载zip包的话我们使用AlamofireAlamofire的下载方法有很多,那么我们使用哪个呢?

1、我们是根据url来下载zip
2、我们下载下来的zip包需要放到自定义的目录下

查看Alamofire文档,我们找到了这个使用介绍(下面这段是摘抄Alamofire文档)

Download File Destination

All downloaded data is initially stored in the system temporary directory. It will eventually be deleted by the system at some point in the future, so if it’s something that needs to live longer, it’s important to move the file somewhere else.

You can provide a Destination closure to move the file from the temporary directory to a final destination. Before the temporary file is actually moved to the destinationURL, the Options specified in the closure will be executed. The two currently supported Options are:

  • .createIntermediateDirectories – Creates intermediate directories for the destination URL if specified.
  • .removePreviousFile – Removes a previous file from the destination URL if specified.
let destination: DownloadRequest.Destination = { _, _ in
    let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
    let fileURL = documentsURL.appendingPathComponent("image.png")

    return (fileURL, [.removePreviousFile, .createIntermediateDirectories])
}

AF.download("https://httpbin.org/image/png", to: destination).response { response in
    debugPrint(response)

    if response.error == nil, let imagePath = response.fileURL?.path {
        let image = UIImage(contentsOfFile: imagePath)
    }
}
复制代码

You can also use the suggested download destination API:

let destination = DownloadRequest.suggestedDownloadDestination(for: .documentDirectory)

AF.download("https://httpbin.org/image/png", to: destination)
复制代码

因此我们在NetworkManager里面写一个download方法

public func download(_ url: String,
                     to destination: DownloadRequest.Destination? = nil,
                     progress: @escaping (Progress) -> Void,
                     responseURL: @escaping (URL) -> Void,
                     failure: @escaping (AppError) -> Void) {
    AF.download(url, to: destination)
        .downloadProgress(closure: progress)
        .response { response in
        if response.error == nil, let filePath = response.fileURL {
            responseURL(filePath)
        } else {
            failure(AppError(code: -1, errorMessage: "下载失败"))
        }
    }
}
复制代码

解压zip

解压zip包,我们使用 Zip库来解压

pod 'Zip'
复制代码
  • 查看Zip的使用文档发现,解压有两个方法(下面这段是摘抄Zip文档)

1、 Quick functions

do {
    let filePath = Bundle.main.url(forResource: "file", withExtension: "zip")!
    let unzipDirectory = try Zip.quickUnzipFile(filePath) // Unzip
} catch {
  print("Something went wrong")
}
复制代码

2、Advanced Zip

For more advanced usage, Zip has functions that let you set custom destination paths, work with password protected zips and use a progress handling closure. These functions throw if there is an error but don’t return.

do {
    let filePath = Bundle.main.url(forResource: "file", withExtension: "zip")!
    let documentsDirectory = FileManager.default.urls(for:.documentDirectory, in: .userDomainMask)[0]
    try Zip.unzipFile(filePath, destination: documentsDirectory, overwrite: true, password: "password", progress: { (progress) -> () in
        print(progress)
    }) // Unzip
} catch {
  print("Something went wrong")
}
复制代码

由于我们解压后的文件需要放到自定义目录里面,所以我们使用第二种方法

下载并解压zip

  • 新建一个ZipManager管理类
class ZipManager: NSObject {
    static let share = ZipManager()
    /// 下载zip包的存放路径
    private let bookZipFilePath = NSHomeDirectory() + "/Documents/BookZip/"
    /// 解压zip包的存放路径
    private let bookUnzipFilePath = NSHomeDirectory() + "/Documents/BookUnzip/"
}
复制代码
  • zip包解压完成后,我们需要删除zip
/// 根据url删除zip文件
private func deleteFile(url: String) {
    let filePath = bookZipFilePath + url.MD5String + url.pathExtension
    do {
        try FileManager.default.removeItem(atPath: filePath)
    } catch {}
}
复制代码
  • 如果绘本存在就直接去取,所以增加一个判断文件是否存在方法
/// 判断该文件是否存在
private func isExistence(url: String) -> Bool {
    let fileName = url.MD5String
    do {
        let files = try FileManager.default.contentsOfDirectory(atPath: bookUnzipFilePath)
        return files.contains(fileName)
    } catch {
        return false
    }
}
复制代码
  • ZipManager里面增加一个解压方法
/// 解压
/// - Parameters:
///   - url: zip包的存放位置
///   - downloadURL: zip包的下载链接,作为解压文件的文件夹名称
///   - unzipProgress: 解压进度回调
private func unzip(_ url: URL,
                   downloadURL: String,
                   unzipProgress: @escaping (Double) -> Void) {
    let filePath = bookUnzipFilePath + downloadURL.MD5String
    let fileURL = URL(fileURLWithPath: filePath)
    do {
        try Zip.unzipFile(url, destination: fileURL, overwrite: true, password: nil, progress: { progress in
            unzipProgress(progress)
            /// 解压完成删除zip包
            if progress >= 1 {
                self.deleteFile(url: downloadURL)
            }
        })
    } catch {
        print("解压失败")
        failure(AppError(code: -1, errorMessage: error.localizedDescription))
    }
}
复制代码
  • ZipManager里面增加一个下载并解压方法
/// 下载并解压
func downloadZipHandler(_ url: String) {
    /// 根据url判断文件是否存在,如果存在直接去取,否则去下载
    if isExistence(url: url) {
        response(getBook(url))
        return
    }
    /// 配置下载的存放路径
    let destination: DownloadRequest.Destination = { _, _ in
        let filePath = self.bookZipFilePath + url.MD5String + url.pathExtension
        let fileURL = URL(fileURLWithPath: filePath)
        return (fileURL, [.removePreviousFile, .createIntermediateDirectories])
    }
    /// 开始下载
    NetworkManager.share.download(url, to: destination) { progress in
        downloadProgress(progress)
    } responseURL: { responseURL in
        /// 下载完成后解压,responseURL就是上面配置的下载的存放路径
        self.unzip(responseURL,
                   downloadURL: url,
                   unzipProgress: unzipProgress)
    } failure: { error in
        failure(error)
    }
}
复制代码

截屏2021-08-10 11.18.52.png

下载并解压就已经做好了,下一篇我们就开始对解压后的文件进行处理

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享