Swift: Unzipping File

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



Leave a reply



Submit