You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I asked this question last Feb but didn't get any response. #257
I would like now to share my solution to unzipInMemory and it seems to work just fine, please see if you like to use it or make it better and hopefully integrate it in this nice library.
The only method you need is unzipInMemory to be added to zip.swift file. I have also included a nice URL extension to use along with sample usage.
Also please let me know if there are issues with the solution or if you have a better approach. Also if we need to create another method for unzipping multiple files in memory or modify this one.
/**
Unzip data in memory.
- parameter data: The Data object containing the zip file content.
- parameter password: An optional password string for encrypted zip files.
- parameter fileOutputHandler: A closure called for each unzipped file, providing the unzipped data and the file name.
- parameter progress: A progress closure called after unzipping each file in the archive, with a Double value between 0 and 1.
- throws: Error if unzipping fails.
- notes: Supports implicit progress composition.
*/
classfunc unzipInMemory(_ zipFilePath:URL, password:String?, fileOutputHandler:@escaping(_ unzippedData:Data, _ fileName:String)->Void)throws{
// File manager
letfileManager=FileManager.default
// Check whether a zip file exists at path.
letpath= zipFilePath.path
guard fileManager.fileExists(atPath: path), !fileExtensionIsInvalid(zipFilePath.pathExtension)else{print("File not found at path: \(path)")throwZipError.fileNotFound
}
// Unzip setup
varret:Int32=0letbufferSize:UInt32=4096varbuffer=[CUnsignedChar](repeating:0, count:Int(bufferSize))
// Begin unzipping
letzip=unzOpen64(path)defer{unzClose(zip)}
if unzGoToFirstFile(zip)!= UNZ_OK {throwZipError.unzipFail
}
repeat {varreadBytes:Int32=0
// Open the current file
if let cPassword = password?.cString(using:.ascii){
ret =unzOpenCurrentFilePassword(zip, cPassword)}else{
ret =unzOpenCurrentFile(zip)}
guard ret == UNZ_OK else{throwZipError.unzipFail
}varfileInfo=unz_file_info64()memset(&fileInfo,0, MemoryLayout<unz_file_info>.size)
ret =unzGetCurrentFileInfo64(zip,&fileInfo,nil,0,nil,0,nil,0)
guard ret == UNZ_OK else{unzCloseCurrentFile(zip)throwZipError.unzipFail
}letfileNameSize=Int(fileInfo.size_filename)+1letfileName= UnsafeMutablePointer<CChar>.allocate(capacity: fileNameSize)defer{free(fileName)}unzGetCurrentFileInfo64(zip,&fileInfo, fileName,UInt(fileNameSize),nil,0,nil,0)fileName[Int(fileInfo.size_filename)]=0letpathString=String(cString: fileName)varfileData=Data()
// Read file data
repeat {
readBytes =unzReadCurrentFile(zip,&buffer, bufferSize)
if readBytes >0{
fileData.append(buffer, count:Int(readBytes))}} while readBytes >0
// Close the current file
letcrcRet=unzCloseCurrentFile(zip)
guard crcRet == UNZ_OK else{throwZipError.unzipFail
}
// Call the output handler with the unzipped data
fileOutputHandler(fileData, pathString)
// Move to the next file
ret =unzGoToNextFile(zip)} while (ret == UNZ_OK)}
extensionURL{
/**
Unzip a zip file located at the URL.
- parameter hash: An optional password string for encrypted zip files.
- parameter progress: An optional closure called with the progress of unzipping, where the Double value is between 0 and 1.
- returns: The content of the unzipped file as a String, or nil if unzipping fails.
- throws: An error if unzipping fails.
- notes: Supports sequential processing of unzipped files.
*/
func unzip(hash:String?=nil, progress:((Double)->Void)?=nil)->String?{varextractedContent:String?letsemaphore=DispatchSemaphore(value:0)do{tryZip.unzipInMemory(self, password: hash){ unzippedData, fileName inprint("Unzipped file: \(fileName), data size: \(unzippedData.count) bytes")
extractedContent =String(decoding: unzippedData, as:UTF8.self)
if let content = extractedContent {print("Content of \(fileName):\n\(content)")}else{print("Unable to convert unzipped data to string for file: \(fileName)")}
semaphore.signal()}
semaphore.wait()return extractedContent
}catch{print("Error unzipping data: \(error.localizedDescription)")returnnil}}}
// MARK: Sample Code - Usage:
structConstants{staticlethash="your_password_hash" // Replace with your actual hash
}
// URL of the zip file
letfileURL=URL(fileURLWithPath:"path/to/your/file.zip")do{try fileURL.unzip(hash:Constants.hash){ unzippedFile inprint("Unzipped file: \(unzippedFile.lastPathComponent)")} progress:{ progress inprint("Progress: \(progress *100)%")}}catch{print("An error occurred during unzipping: \(error.localizedDescription)")}
The text was updated successfully, but these errors were encountered:
waelsaad
changed the title
Finally - A Proposed Working Solution to Efficiently Unzipping Password-Protected File in Memory Using Swift (Solution is Here)
Finally - A Proposed Working Solution to Efficiently Unzipping Password-Protected File in Memory Using this Swift Library (Solution is Here)
Sep 20, 2024
Hi,
I asked this question last Feb but didn't get any response. #257
I would like now to share my solution to unzipInMemory and it seems to work just fine, please see if you like to use it or make it better and hopefully integrate it in this nice library.
The only method you need is unzipInMemory to be added to zip.swift file. I have also included a nice URL extension to use along with sample usage.
If you like it feel free to nominate a star :] https://stars.github.com/nominate/
Also please let me know if there are issues with the solution or if you have a better approach. Also if we need to create another method for unzipping multiple files in memory or modify this one.
// MARK: Sample Code - Usage:
The text was updated successfully, but these errors were encountered: