ver para leer descomprimir descargar como bajar archivos archivo app aplicacion abrir ios swift streaming archive unzip

ios - para - ¿Cómo descomprimir un archivo zip grande que contiene un archivo y obtener el progreso en bytes con swift?



leer archivos zip iphone (3)

Intento descomprimir un archivo zip grande que contiene un solo elemento (más de 100 MB) y me gusta mostrar el progreso durante la descompresión.

Encontré soluciones donde el progreso se puede determinar en función de la cantidad de archivos descomprimidos, pero en mi caso solo tengo un archivo grande dentro. Así que supongo que debe ser determinado por la cantidad de bytes descomprimidos?

En realidad estoy usando SSZipArchive con el siguiente código que funciona bien:

var myZipFile:NSString="/Users/user/Library/Developer/CoreSimulator/Devices/mydevice/ziptest/testzip.zip"; var DestPath:NSString="/Users/user/Library/Developer/CoreSimulator/Devices/mydevice/ziptest/"; let unZipped = SSZipArchive.unzipFileAtPath(myZipFile as! String, toDestination: DestPath as! String);

No encontré soluciones para esto.

¿Alguien tiene una sugerencia, muestra o enlace a una muestra?

ACTUALIZACIÓN: el siguiente código parece que funcionaría como estaba previsto, pero se llamará al controlador solo una vez (al final de la descompresión) cuando se descomprima el único archivo:

func unzipFile(sZipFile: String, toDest: String){ SSZipArchive.unzipFileAtPath(sZipFile, toDestination: toDest, progressHandler: { (entry, zipInfo, readByte, totalByte) -> Void in println("readByte : /(readByte)") // <- This will be only called once, at the end of unzipping. My 500MB Zipfile holds only one file. println("totalByte : /(totalByte)") //Asynchrone task dispatch_async(dispatch_get_main_queue()) { println("readByte : /(readByte)") println("totalByte : /(totalByte)") //Change progress value } }, completionHandler: { (path, success, error) -> Void in if success { //SUCCESSFUL!! } else { println(error) } }) }

ACTUALIZACIÓN 2:

Como "Martin R" analizó en SSArchive, no es posible. ¿Hay alguna otra manera de descomprimir un archivo y mostrar los kbytes basados ​​en el progreso?

ACTUALIZACIÓN 3:

Cambié el SSZipArchive.m después de que la solución se explicara por "roop" de la siguiente manera. Probablemente alguien más puede usar esto también:

FILE *fp = fopen((const char*)[fullPath UTF8String], "wb"); while (fp) { int readBytes = unzReadCurrentFile(zip, buffer, 4096); if (readBytes > 0) { fwrite(buffer, readBytes, 1, fp ); totalbytesread=totalbytesread+4096; // Added by me if (progressHandler) { progressHandler(strPath, fileInfo, currentFileNumber, totalbytesread); } // End added by me } else { break; } }


Para lograr lo que desea, tendrá que modificar el código interno de SSZipArchive.

SSZipArchive usa minizip para proporcionar la funcionalidad de compresión. Puede ver la API de descompresión de minizip aquí: unzip.h .

En SSZipArchive.m, puede obtener el tamaño descomprimido del archivo que se está descomprimiendo de la variable fileInfo .

Puedes ver que los contenidos descomprimidos se están leyendo here :

FILE *fp = fopen((const char*)[fullPath UTF8String], "wb"); while (fp) { int readBytes = unzReadCurrentFile(zip, buffer, 4096); if (readBytes > 0) { fwrite(buffer, readBytes, 1, fp ); } else { break; } }

Necesitará los readBytes y el tamaño del archivo sin comprimir para calcular el progreso de un solo archivo. Puede agregar un nuevo delegado a SSZipArchive para enviar estos datos al código de llamada.


Por lo que entendí, la respuesta más obvia sería modificar el código interno de SSZipArchive. Pero decidí ir por otro camino y escribí esta extensión. Es bastante simple de entender, pero no dude en hacer cualquier pregunta.

Además, si crees que mi solución tiene fallas o sabes cómo mejorarla, me encantaría escucharla.

Aquí hay una solución:

import Foundation import SSZipArchive typealias ZippingProgressClosure = (_ zipBytes: Int64, _ totalBytes: Int64) -> () private typealias ZipInfo = (contentSize: Int64, zipPath: String, progressHandler: ZippingProgressClosure) extension SSZipArchive { static func createZipFile(atPath destinationPath: String, withContentsOfDirectory contentPath: String, keepParentDirectory: Bool, withPassword password: String? = nil, byteProgressHandler: @escaping ZippingProgressClosure, completionHandler: @escaping ClosureWithSuccess) { DispatchQueue.global(qos: .background).async { var timer: Timer? = nil DispatchQueue.main.async { //that''s a custom function for folder''s size calculation let contentSize = FileManager.default.sizeOfFolder(contentPath) timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(progressUpdate(_:)), userInfo: ZipInfo(contentSize: contentSize, zipPath: destinationPath, progressHandler: byteProgressHandler), repeats: true) } let isSuccess = SSZipArchive.createZipFile(atPath: destinationPath, withContentsOfDirectory: contentPath, keepParentDirectory: keepParentDirectory, withPassword: password, andProgressHandler: nil) DispatchQueue.main.async { timer?.invalidate() timer = nil completionHandler(isSuccess) } } } @objc private static func progressUpdate(_ sender: Timer) { guard let info = sender.userInfo as? ZipInfo, FileManager.default.fileExists(atPath: info.zipPath), let zipBytesObj = try? FileManager.default.attributesOfItem(atPath: info.zipPath)[FileAttributeKey.size], let zipBytes = zipBytesObj as? Int64 else { return } info.progressHandler(zipBytes, info.contentSize) } }

Y el método se usa así:

SSZipArchive.createZipFile(atPath: destinationUrl.path, withContentsOfDirectory: fileUrl.path, keepParentDirectory: true, byteProgressHandler: { (zipped, expected) in //here''s the progress code }) { (isSuccess) in //here''s completion code }

Pros: No es necesario modificar el código interno, que se sobrescribirá con la actualización de pods

Contras: Como puede ver, estoy actualizando la información del tamaño del archivo con un intervalo de 0,1 segundos. No sé si recuperar los metadatos del archivo puede causar una sobrecarga de rendimiento y no puedo encontrar ninguna información al respecto.

De todos modos, espero poder ayudar a alguien :)


Puedes probar este código:

SSZipArchive.unzipFileAtPath(filePath, toDestination: self.destinationPath, progressHandler: { (entry, zipInfo, readByte, totalByte) -> Void in //Create UIProgressView //Its an exemple, you can create it with the storyboard... var progressBar : UIProgressView? progressBar = UIProgressView(progressViewStyle: .Bar) progressBar?.center = view.center progressBar?.frame = self.view.center progressBar?.progress = 0.0 progressBar?.trackTintColor = UIColor.lightGrayColor(); progressBar?.tintColor = UIColor.redColor(); self.view.addSubview(progressBar) //Asynchrone task dispatch_async(dispatch_get_main_queue()) { println("readByte : /(readByte)") println("totalByte : /(totalByte)") //Change progress value progressBar?.setProgress(Float(readByte/totalByte), animated: true) //If progressView == 100% then hide it if readByte == totalByte { progressBar?.hidden = true } } }, completionHandler: { (path, success, error) -> Void in if success { //SUCCESSFUL!! } else { println(error) } })

¡Espero haberte ayudado!

Ysee