这是我参与8月更文挑战的第14天,活动详情查看:8月更文挑战
前言
视频和音频播放都已经搞完了,接下来就搞下读绘本吧。
抓取接口数据发现,里面有个url
字段,url
是一个zip
链接
用浏览器打开一个链接将其下载下来并解压
通过上面的截图可以看到,里面包含了图片和音频资源,还有一个index.json
文件
index.json
文件是绘本的信息,包含图片和音频名称、音频时长
读绘本其实就是一张图片配个音频,滑到哪张图片播放哪个音频。所以现在的步骤是:
1、下载
zip
包
2、解压zip
包
3、处理解压后的包
4、播放
下载zip
包
下载zip
包的话我们使用Alamofire
。Alamofire
的下载方法有很多,那么我们使用哪个呢?
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库来解压
- 使用 CocoaPods导入
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)
}
}
复制代码
下载并解压就已经做好了,下一篇我们就开始对解压后的文件进行处理