A. Amini
A. Amini

Reputation: 561

Create Zip file from an array of data (coreData Images) and share via the .zip file via Email

I have an (n) of data (UIImage JPEG) inside my CoreData.

let imageData: [Data]... 

I have already this two frameworks/ Pods: Zip and ZIPFoundation

I have a few Question about that:

  1. I need to create a temp URL for each of my imageData?
  2. If yes, I have to add tempURL.appendingPathExtension("jpg") to each temp URLs before or after call data.write(to: tempURL) ?

After that, I have an Array of URLs, so I just need to create a Zip File and share it. But it doesn't work, I get a .zip - .cpgz Loop on my Mac.

 private func createURLsFrom(imageData: [ImageData]?) {
    var urlArray = [URL]()
    imageData?.forEach { imData in
        if let data = imData.imageData,
        let tempURL = NSURL.fileURL(withPathComponents: [NSTemporaryDirectory(), NSUUID().uuidString])?.appendingPathExtension("jpg") {

            do {
                try data.write(to: tempURL)
                urlArray.append(tempURL)

            } catch {...}
        }
    }
    self.createZipFile(urlArray: urlArray)
}



private func createZipFile(urlArray: [URL]) {
    if let zipURL = try? Zip.quickZipFiles(urlArray, fileName: "ZIP_Test1") {
        self.sendEmailWith(dataURL: zipURL)
    } else {...}
}


private func sendEmailWith(dataURL: URL) {
    if MFMailComposeViewController.canSendMail() {

        let mailComposer = MFMailComposeViewController()
        mailComposer.mailComposeDelegate = self

        mailComposer.setSubject("setSubject")
        mailComposer.setMessageBody("setMessageBody", isHTML: false)
        mailComposer.addAttachmentData(dataURL.dataRepresentation, mimeType: "application/zip", fileName: ("ZIP_Test1.zip"))

        self.present(mailComposer, animated: true, completion: nil)
    }
}

What am I doing wrong :(

Upvotes: 9

Views: 1403

Answers (3)

A. Amini
A. Amini

Reputation: 561

After a lot of debugging finally, I found the problem. First of all Daniels answer was correct too.

But the main issue was my sendEmailWith function, "application/zip" is not working!

So I added UIActivityViewController with the directory URL and it's work.

Now I can share my Zip file via Mail and Airdrop!

Upvotes: 0

Daniel
Daniel

Reputation: 3597

It's a bit lengthy, and––disclaimer––untested. Let me know if it works or if you have any questions.

Create a temp directory for all the files:

func createTempDirectory() -> URL? {
    if let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first {
        let dir = documentDirectory.appendingPathComponent("temp-dir-\(UUID().uuidString)")
        do {
            try FileManager.default.createDirectory(atPath: dir.path, withIntermediateDirectories: true, attributes: nil)
        } catch {
            print(error.localizedDescription)
        }
        return dir
    } else {
        return nil
    }
}

Save all the images to the temp directory:

func saveImages(data: [Data]) -> URL? {
    guard let directory = createTempDirectory() else { return nil }

    do {
        for (i, imageData) in data.enumerated() {
            try imageData.write(to: directory.appendingPathComponent("image\(i).jpg"))
        }
        return directory
    } catch {
        return nil
    }
}

Get the URL for the zipped file. This is an optional in case an error occurred along the way. Also, done on a background thread because it could take a bit of time, and you don't want to block the main thread.

func zipImages(data: [Data], completion: @escaping ((URL?) -> ())) {
    DispatchQueue.main.async {
        guard let directory = saveImages(data: data) else {
            completion(nil)
            return
        }

        do {
            let zipFilePath = try Zip.quickZipFiles([directory], fileName: "archive-\(UUID().uuidString)")
            completion(zipFilePath)
        } catch {
            completion(nil)
        }
    }
}

After you send the file, you'll probably want to delete the temp directory so your app size doesn't start growing.

Upvotes: 4

Jon Rose
Jon Rose

Reputation: 8563

Move the

self.createZipFile(urlArray: urlArray)

to after the forEach loop.

Upvotes: -1

Related Questions