Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to unzip a big zip file containing one file and get the progress in bytes with swift?

I try to unzip a big zip file containing only one item (more than 100MB) and like to show the progress during unzipping.

I found solutions where the progress can be determined based on the amount of files unzipped but in my case I have only one big file inside. So I guess it must be determined by the amount of bytes unzipped?

Actually I am using SSZipArchive with the following code which works fine:

    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);

I found no solutions for this.

Does anyone have a hint, sample or link to a sample ?

UPDATE: Following code looks like it would work as intended, but the handler will be called only once (at the end of unzipping) when the only one file is unzipped:

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)
                }
        })

    }

UPDATE 2:

As "Martin R" analysed in SSArchive, its not possible. Is there any other way to unzip a file and show the progress based kbytes?

UPDATE 3:

I changed the SSZipArchive.m after the solution was explained by "roop" as follows. Probably someone else can use this too:

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;
                    }
                }
like image 672
mcfly soft Avatar asked May 14 '15 07:05

mcfly soft


People also ask

How do I unzip a large zip file?

To unzip files Open File Explorer and find the zipped folder. To unzip the entire folder, right-click to select Extract All, and then follow the instructions. To unzip a single file or folder, double-click the zipped folder to open it. Then, drag or copy the item from the zipped folder to a new location.

How can I extract a ZIP file more than 4GB?

If you are using Wiredrive to download large zip files, you may need to download and use a 64-bit unarchiving tool. If any single file in your zip file is over 4GB, then a 64-bit unarchiving program is required to open the . zip file, otherwise you will get a loop and be unable to extract the files.

How do I unzip a file in Swift?

let unzipDirectory= try Zip. quickUnzipFile(filePath) //to unZip your folder. If you want more help , check the repository. This is related to using a third-party library, if you are not using it, this code will generate compile time error.

Can you extract a ZIP file multiple times?

WinZip can quickly unzip multiple files through its drag and drop interface. You can select multiple WinZip files, right click, and drag them to a folder to unzip them all with one operation. To unzip multiple Zip files without drag and drop: From an open folder window, highlight the WinZip files you want to Extract.


1 Answers

To achieve what you want, you will have to modify SSZipArchive's internal code.

SSZipArchive uses minizip to provide the zipping functionality. You can see the minizip unzipping API here: unzip.h.

In SSZipArchive.m, you can get the uncompressed size of the file being unzipped from the fileInfo variable.

You can see that the unzipped contents are being read 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;
     }
 }

You will need the readBytes and the uncompressed file size to compute the progress for a single file. You can add a new delegate to SSZipArchive to send these data back to the calling code.

like image 166
roop Avatar answered Sep 20 '22 23:09

roop