How to convert data(Type Data) to a zip file(Type File) in swift 4 and cocoa for Mac OS App?

Hi there. I am developing a mac os application where i have to convert the data from server API to a zip file. The API is returning a zip file itself in encoded format of type Data, but i want to convert that data to a zip file and want to store in the disk.


CODE:

______


    func DownloadExamZip(){
        let request = NSMutableURLRequest(url: NSURL(string: "http://localhost:5000/api/DownloadExamZip/EX0000018/ST000000195/874059")! as URL)
        request.httpMethod = "GET"
        let AuthorizationToken = "Hidden"
        request.setValue("application/x-www-form-urlencoded; charset=utf-8", forHTTPHeaderField: "Content-Type")
        request.setValue(AuthorizationToken, forHTTPHeaderField: "Authorization")
        let task = URLSession.shared.dataTask(with: request as URLRequest) { data, response, error in
            do {
                guard data != nil else {
                    print("data is nil")
                    return
                }
                //Here i want to convert the type data to a zip file
                
            }
            catch {
                print("Error -> \(error)")
            }
        }
        task.resume()
    }

Can anyone help me to convert that data into a zip file please. I also have to store that file in the disk.

Accepted Reply

You can get a URL for the Documents directory using

FileManager
.
let docDir = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)

Be aware that this only works the way you expect it to work if your app is not sandboxed. If your app is sandboxed — and all Mac App Store apps must be sandboxed — things get more complex. Let me know if that’s the case and I can go into the details.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Replies

If I’m reading this correctly it seems that the server is returning you data in Zip format and you then want to create a

.zip
file from that data. That is, you don’t need to extract items from the Zip file, or create a Zip file from scratch, you just want to take existing Zip data and turn it into a
.zip
file.

If so, that’s quite straightforward: You can just write the data to disk using a

.zip
file extension. For example, assuming
data
is the data you want to write and
destinationDir
is a URL pointing to the destination directory, you could write code like this:
let destination = destinationDir.appendingPathComponent("SomeFileName.zip")
try data.write(to: destination)

ps Your data task completion handler should check for errors. There’s actually three types of errors to check for:

  1. First look at

    error
    . If it’s not
    nil
    , there was an error sending your request to, or receiving the response from, your server.
  2. Next look at

    response
    , and specifically the HTTP status code. You’d expect it to be something in the 200...299 range. Other status indicate that there was an error on the server.
  3. I also recommend that you look at the

    Content-Type
    returned by the server to make sure it’s actually a
    .zip
    file.

Putting this all together you’d get something like this:

URLSession.shared.dataTask(with: request) { (data, response, error) in
    if let error = error as NSError? {
        … deal with the transport error …
    }
    let response = response as! HTTPURLResponse
    guard (200...299).contains(response.statusCode) else {
        … deal with the server-side error …
    }
    guard response.mimeType == "application/zip" else {
        … deal with the bogus `Content-Type` …
    }
    let data = data!
    … if nothing failed, save `data` as a `.zip` file …
}.resume()

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thank you for answering 🙂. Can you help me one more thing please. Actually i am assigning the diskpath to that "destinationDir" but its showing error. I want to write that zip file in my Documents folder of the Mac HDD, can you tell me how to assign url path for Documents folder to that "destinationDir" please.


Here is the directory structure of my mac:

Bishnu-iMac:~ bishnudas$ ls
AndroidStudioProjects Downloads Pictures
Applications Library Projects
Desktop Movies Public
Documents Music


Bishnu-iMac:~ bishnudas$ /Users/bishnudas/Library/Developer/Xcode/DerivedData/Unox_Student_Console-eusdgzuqihnqizfqtjziyidlhyen/Build/Products/Debug/Unox\ Student\ Console.app/Contents/MacOS/Unox\ Student\ Console

You can get a URL for the Documents directory using

FileManager
.
let docDir = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)

Be aware that this only works the way you expect it to work if your app is not sandboxed. If your app is sandboxed — and all Mac App Store apps must be sandboxed — things get more complex. Let me know if that’s the case and I can go into the details.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thank you. It worked perfectly.

Actually i need one more help please.

I have downloaded the zip file at the following path :

let destinationDir = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)

The zip file contains several files including json files. I want to extract that zip file and read the json files, so that i will store that json file in one json object in my swift code for my use. Can you tell me how to extract that zip file and read the files and directories inside the zip.

Can you tell me how to extract that zip file and read the files and directories inside the zip.

macOS does not have any APIs for packing or unpacking

.zip
files. This is, IMO, an annoying limitation and if you’d like to see such APIs added to the system I encourage you to file an enhancement request describing your requirements. Please post your bug number, just for the record.

In the meantime you have a number of options:

  • You can write your own code for unpacking a

    .zip
    file.
  • You can use a third-party library for this. There are lots of them around, but I don’t have a specific recommendation because I’ve not used any of them.

  • You can use

    Process
    to run the
    unzip
    tool to do this job (this only works because you’re on macOS; our other platforms don’t include this support).

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Okay i got it. I hope apple will add some missing features to swift very soon.

I hope apple will add some missing features to swift very soon.

Please don’t just hope, but rather file an enhancement request describing your requirements so that the macOS Engineering team understands the level of demand for this feature.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Yeah sure, you are right.

Actually i found one third party library for zip file management in swift. I have downloaded that package. But i dont know how to manage or include external libraries in swift. Can you give me some idea.

There are multiple schools of thought here:

  • You can use Swift Package Manager.

  • You can use a third-party package manager, the two most common being CocoaPods and Carthage.

  • You can just extract the relevant bits of code and take ownership of them yourself.

All of these have their pros and cons, and I’m not the right person to offer opinions on the various automated solutions because I don’t use any of them. Sorry.

You might try asking this specific question over in the Xcode > Swift topic area, where you’re more likely to find folks with concrete experience with this.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thank you buddy 🙂. I installed cocoapods and it is working well.

Code Block
    if let fileData = input.data(using: .hexadecimal){
        print(fileData)
        do {
            let compressedData = try (fileData as NSData).compressed(using: .lzma)
            print(compressedData)
            let file = "myfile.zip"
            if let dir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first {
                let fileURL = dir.appendingPathComponent(file)
                do {
                    let url: () = try compressedData.write(to: fileURL, options: .atomic)
                    print(url)
                } catch {
                    print(error)
                }
            }
        }catch{
            print(error.localizedDescription)
        }
    }