Decompress a zip file with Swift
I recently released a Swift native framework that allows you to create, read and update ZIP archive files: ZIP Foundation.
It internally uses libcompression for great compression performance.
Unzipping a file is basically just one line:
try fileManager.unzipItem(at: sourceURL, to: destinationURL)
A full example with some context would look like this:
let fileManager = FileManager()
let currentWorkingPath = fileManager.currentDirectoryPath
var sourceURL = URL(fileURLWithPath: currentWorkingPath)
sourceURL.appendPathComponent("archive.zip")
var destinationURL = URL(fileURLWithPath: currentWorkingPath)
destinationURL.appendPathComponent("directory")
do {
try fileManager.createDirectory(at: destinationURL, withIntermediateDirectories: true, attributes: nil)
try fileManager.unzipItem(at: sourceURL, to: destinationURL)
} catch {
print("Extraction of ZIP archive failed with error:\(error)")
}
The README on GitHub contains more information. All public methods also have full documentation available via Xcode Quick Help.
I also wrote a blog post about the performance characteristics here.
Swift: unzipping file
ZIP Foundation supports accessing individual entries in ZIP archives.
You have to initialize an archive by passing a file URL to the Archive
initializer.
Afterwards you can access a specific entry via subscripting:
let fileManager = FileManager()
let currentWorkingPath = fileManager.currentDirectoryPath
var archiveURL = URL(fileURLWithPath: currentWorkingPath)
archiveURL.appendPathComponent("test.zip")
guard let archive = Archive(url: archiveURL, accessMode: .read) else {
return
}
guard let entry = archive["file.txt"] else {
return
}
var destinationURL = URL(fileURLWithPath: currentWorkingPath)
destinationURL.appendPathComponent("out.txt")
do {
try archive.extract(entry, to: destinationURL)
} catch {
print("Extracting entry from archive failed with error:\(error)")
}
You can also directly access the contents of entry
by using the closure based API. This allows you to process the entry without writing it to the file system first:
try archive.extract(entry, consumer: { (data) in
print(data.count)
})
Unzip a zip file coming from server without locally saving in ios swift similar to what android does?
This is the answer which I was hoping for. Finally found one in stackoverflow https://stackoverflow.com/a/30456344/1954633
Swift Unzipping zip file and find xml file from base64 data from Gmail API
Finally I found it. As it is mentioned in Ref 1,The email bodies are encoded in 7-bit US-ASCII data. So this is why the base64 decoding did not work.
As defined in the rfc1341:
An encoding type of 7BIT requires that the body is already in a
seven-bit mail- ready representation. This is the default value --
that is, "Content-Transfer-Encoding: 7BIT" is assumed if the
Content-Transfer-Encoding header field is not present.
The whole code worked after adding the following.
let edata: String = result.data.replacingOccurrences(of: "-", with: "+").replacingOccurrences(of: "_", with: "/")
As it is mentioned in Ref 2, it just need character replacement on '-' with '+' and '_' with '/' inside base64 data received from gmail api.
func getAttachedData(messageId: String, attachmentId: String) {
decode(self.urlBase+messageId+"/attachments/"+attachmentId+"?"+self.urlKey) { (result: Attachment) in
let edata: String = result.data.replacingOccurrences(of: "-", with: "+").replacingOccurrences(of: "_", with: "/")
if let data = Data(base64Encoded: edata, options: .ignoreUnknownCharacters) {
let filemanager = FileManager.default
let path = try! filemanager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
let url = path.appendingPathComponent(messageId+".zip")
do {
try data.write(to: url)
} catch {
print("Error while writing: "+error.localizedDescription)
}
do {
let unzipDirectory = try Zip.quickUnzipFile(url)
print("Unzipped")
do {
let filelist = try filemanager.contentsOfDirectory(at: unzipDirectory, includingPropertiesForKeys: [], options: [])
for filename in filelist {
print(filename.lastPathComponent)
print(filename.relativeString)
do {
let text = try String(contentsOf: filename, encoding: .utf8)
print(text)
DispatchQueue.main.async {
self.attachments.append(text)
}
} catch let error as NSError {
print("Error: \(error.localizedDescription)")
}
}
} catch let error {
print("Error: \(error.localizedDescription)")
}
} catch let error as NSError {
print("Error while unzipping: "+error.localizedDescription)
}
}
}
}
Ref 1: https://stackoverflow.com/a/58590759/2382813
Ref 2: https://stackoverflow.com/a/24986452/2382813
Related Topics
Xcode 6.1 Swift Extensions - Sourcekit Service Crash
Swift: Guard Let and Where - The Priority
Parsing JSON from Url Ends Up with an Error - Swift 5
Invalid Update: Invalid Number of Rows in Section 1
Do Protocols Have an Effect on The Retain Count
Switch Statement Where Value Is Int But Case Can Contain Array
Swiftui Change on Multilevel Children Published Object Change
Public Default Init in Protocol
Swiftui - How to Change The Button's Image on Click
Upload Multiple Images to Ftp Server in iOS
Swiftui Section from Attribute of a Struct
Support Arkit in Lower End Devices
Create Record Only If Parent Exists in Vapor Using Fluent
Using Nsdate to Get Date for Easter
Add a File Generated by Run Script into The Test Target Compilation List in Xcode
Http Status 415 When Using Alamofire Multipart Upload