From 1d615e939b2667e61284773b63c93355754db248 Mon Sep 17 00:00:00 2001 From: Roy Marmelstein Date: Sun, 17 Jan 2016 06:35:15 +0100 Subject: [PATCH] Improving type safety, clearer variables --- Zip/QuickZip.swift | 2 +- Zip/Zip.swift | 95 +++++++++++++++++++++++++++++------------ ZipTests/ZipTests.swift | 13 ++++++ 3 files changed, 81 insertions(+), 29 deletions(-) diff --git a/Zip/QuickZip.swift b/Zip/QuickZip.swift index d75d7dd..0bdd311 100644 --- a/Zip/QuickZip.swift +++ b/Zip/QuickZip.swift @@ -74,7 +74,7 @@ extension Zip { */ public func quickZipFiles(paths: [NSURL], fileName: String, progress: ((progress: Double) -> ())?) throws -> NSURL { let destinationUrl = documentsUrl.URLByAppendingPathComponent("\(fileName).zip") - try self.zipFiles(paths, destination: destinationUrl, password: nil, progress: progress) + try self.zipFiles(paths, zipFilePath: destinationUrl, password: nil, progress: progress) return destinationUrl } diff --git a/Zip/Zip.swift b/Zip/Zip.swift index 977c81d..ad034cf 100644 --- a/Zip/Zip.swift +++ b/Zip/Zip.swift @@ -28,6 +28,9 @@ public enum ZipError: ErrorType { public class Zip { + // File manager + let fileManager = NSFileManager.defaultManager() + // Documents folder let documentsUrl = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0] as NSURL @@ -46,31 +49,41 @@ public class Zip { /** Unzip file - - parameter path: Path of zipped file. NSURL. - - parameter destination: Path to unzip to. NSURL. + - parameter zipFilePath: Local file path of zipped file. NSURL. + - parameter destination: Local file path to unzip to. NSURL. - parameter overwrite: Overwrite bool. - parameter password: Optional password if file is protected. - parameter progress: A progress closure called after unzipping each file in the archive. Double value betweem 0 and 1. - throws: Error if unzipping fails or if fail is not found. Can be printed with a description variable. */ - public func unzipFile(path: NSURL, destination: NSURL, overwrite: Bool, password: String?, progress: ((progress: Double) -> ())?) throws { + + public func unzipFile(zipFilePath: NSURL, destination: NSURL, overwrite: Bool, password: String?, progress: ((progress: Double) -> ())?) throws { + // Check whether a zip file exists at path. - let fileManager = NSFileManager.defaultManager() - if fileManager.fileExistsAtPath(path.path!) == false || path.pathExtension != "zip" { + guard let path = zipFilePath.path, let destinationPath = destination.path else { + throw ZipError.FileNotFound + } + if fileManager.fileExistsAtPath(path) == false || zipFilePath.pathExtension != "zip" { throw ZipError.FileNotFound } + // Unzip set up var ret: Int32 = 0 var crc_ret: Int32 = 0 let bufferSize: UInt32 = 4096 var buffer = Array(count: Int(bufferSize), repeatedValue: 0) - // Begin unzipping - let zip = unzOpen64(path.path!) - let fileAttributes = try fileManager.attributesOfItemAtPath(path.path!) - let totalSize = fileAttributes[NSFileSize] as? Double + // Progress handler set up + var totalSize: Double = 0.0 var currentPosition: Double = 0.0 + let fileAttributes = try fileManager.attributesOfItemAtPath(path) + if let attributeFileSize = fileAttributes[NSFileSize] as? Double { + totalSize += attributeFileSize + } + + // Begin unzipping + let zip = unzOpen64(path) if unzGoToFirstFile(zip) != UNZ_OK { throw ZipError.UnzipFail } @@ -104,7 +117,7 @@ public class Zip { } var isDirectory = false let fileInfoSizeFileName = Int(fileInfo.size_filename-1) - if (fileName[fileInfoSizeFileName] == "/".cStringUsingEncoding(NSUTF8StringEncoding)!.first! || fileName[fileInfoSizeFileName] == "\\".cStringUsingEncoding(NSUTF8StringEncoding)!.first!) { + if (fileName[fileInfoSizeFileName] == "/".cStringUsingEncoding(NSUTF8StringEncoding)?.first || fileName[fileInfoSizeFileName] == "\\".cStringUsingEncoding(NSUTF8StringEncoding)?.first) { isDirectory = true; } free(fileName) @@ -121,7 +134,7 @@ public class Zip { try fileManager.createDirectoryAtPath(fullPath, withIntermediateDirectories: true, attributes: directoryAttributes) } else { - try fileManager.createDirectoryAtPath(destination.path!, withIntermediateDirectories: true, attributes: directoryAttributes) + try fileManager.createDirectoryAtPath(destinationPath, withIntermediateDirectories: true, attributes: directoryAttributes) } } catch {} if fileManager.fileExistsAtPath(fullPath) && !isDirectory && !overwrite { @@ -144,11 +157,16 @@ public class Zip { if crc_ret == UNZ_CRCERROR { throw ZipError.UnzipFail } - if let progressHandler = progress, let totalSize = totalSize{ + ret = unzGoToNextFile(zip) + + // Update progress handler + if let progressHandler = progress{ progressHandler(progress: (currentPosition/totalSize)) } - ret = unzGoToNextFile(zip) + } while (ret == UNZ_OK && ret != UNZ_END_OF_LIST_OF_FILE) + + // Completed. Update progress handler. if let progressHandler = progress{ progressHandler(progress: 1.0) } @@ -161,41 +179,53 @@ public class Zip { Zip files. - parameter paths: Array of NSURL filepaths. - - parameter destination: Destination NSURL, should lead to a .zip filepath. + - parameter zipFilePath: Destination NSURL, should lead to a .zip filepath. - parameter password: Password string. Optional. - parameter progress: A progress closure called after unzipping each file in the archive. Double value betweem 0 and 1. - throws: Error if zipping fails. */ - public func zipFiles(paths: [NSURL], destination: NSURL, password: String?, progress: ((progress: Double) -> ())?) throws { + public func zipFiles(paths: [NSURL], zipFilePath: NSURL, password: String?, progress: ((progress: Double) -> ())?) throws { + + // Check whether a zip file exists at path. + guard let destinationPath = zipFilePath.path else { + throw ZipError.FileNotFound + } + + // Zip set up let chunkSize: Int = 16384 - let fileManager = NSFileManager.defaultManager() + + // Progress handler set up var currentPosition: Double = 0.0 var totalSize: Double = 0.0 - // Check if paths exist and get totalSize for progress handler + // Get totalSize for progress handler for path in paths { - if fileManager.fileExistsAtPath(path.path!) == false { - throw ZipError.FileNotFound - } do { - let fileAttributes = try fileManager.attributesOfItemAtPath(path.path!) - let fileSize = fileAttributes[NSFileSize] as? Double - if let fileSize = fileSize { - totalSize += fileSize + if let filePath = path.path { + let fileAttributes = try fileManager.attributesOfItemAtPath(filePath) + let fileSize = fileAttributes[NSFileSize] as? Double + if let fileSize = fileSize { + totalSize += fileSize + } } } catch {} } - let zip = zipOpen(destination.path!, APPEND_STATUS_CREATE) + + // Begin Zipping + let zip = zipOpen(destinationPath, APPEND_STATUS_CREATE) for path in paths { - let input = fopen(path.path!, "r") + guard let filePath = path.path else { + throw ZipError.ZipFail + } + let input = fopen(filePath, "r") if input == nil { throw ZipError.ZipFail } let fileName = path.lastPathComponent var zipInfo: zip_fileinfo = zip_fileinfo(tmz_date: tm_zip(tm_sec: 0, tm_min: 0, tm_hour: 0, tm_mday: 0, tm_mon: 0, tm_year: 0), dosDate: 0, internal_fa: 0, external_fa: 0) do { - let fileAttributes = try fileManager.attributesOfItemAtPath(path.path!) + let fileAttributes = try fileManager.attributesOfItemAtPath(filePath) if let fileDate = fileAttributes[NSFileModificationDate] as? NSDate { let components = NSCalendar.currentCalendar().components([.Year, .Month, .Day, .Hour, .Minute, .Second], fromDate: fileDate) zipInfo.tmz_date.tm_sec = UInt32(components.second) @@ -225,14 +255,23 @@ public class Zip { length = fread(buffer, 1, chunkSize, input) zipWriteInFileInZip(zip, buffer, UInt32(length)) } + + // Update progress handler if let progressHandler = progress{ progressHandler(progress: (currentPosition/totalSize)) } + zipCloseFileInZip(zip) free(buffer) fclose(input) } - zipClose(zip, nil); + zipClose(zip, nil) + + // Completed. Update progress handler. + if let progressHandler = progress{ + progressHandler(progress: 1.0) + } + } diff --git a/ZipTests/ZipTests.swift b/ZipTests/ZipTests.swift index 7ef0e08..2e0c8d5 100644 --- a/ZipTests/ZipTests.swift +++ b/ZipTests/ZipTests.swift @@ -68,6 +68,19 @@ class ZipTests: XCTestCase { } } + func testUnzipOnlineURL() { + do { + let fileAbsoluteURL = NSURL(string: "http://www.google.com/google.zip")! + let destinationURL = try Zip().quickUnzipFile(fileAbsoluteURL) + let fileManager = NSFileManager.defaultManager() + XCTAssertFalse(fileManager.fileExistsAtPath(destinationURL.path!)) + } + catch { + XCTAssert(true) + } + } + + func testQuickZip() { do { let imageURL1 = NSBundle(forClass: ZipTests.self).URLForResource("3crBXeO", withExtension: "gif")! -- 2.26.2