Open and unzip with the ZipArchive class fails

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • jeddiki
    Contributor
    • Jan 2009
    • 290

    Open and unzip with the ZipArchive class fails

    Hi,

    So far, last Friday, every file file I try and open and unzip with
    the ZipArchive class has failed.

    I have just used ZipArchive to create a zip file and then
    attempt to unzip it.

    Even this has failed.

    Does this means that my server ZipArchive class is somehow corrupted ?

    Should I reinstall that php class ( I think it is via PECL )

    Or is there another reason ?

    here is my script for creating the zip file
    and then unzipping it.

    ( Because I am trying to trap every error it is longer than usual )

    Code:
    $new_zip = $file_dir.'aaa_new.zip';
    
    if (!class_exists('ZipArchive')) {
       write_log("Class ZipArchive not found\r\n"); 
       exit;
    	 } 
    else {
      write_log("Class ZipArchive OK\r\n"); 
      $zip = new ZipArchive;
    }
    
    $res = $zip->open($new_zip, ZipArchive::CREATE);
    if ($res === TRUE) {
        $zip->addFromString('data1.txt', 'file content goes here');
        $fin = $zip->close();
    		if ($fin === TRUE) {
           write_log("Created zip file: $new_zip\r\n");
           } 
        else {
           write_log("Error on close: $fin \r\n");
    		   exit;  
    		   }   
        }
    else {
        write_log("Could NOT Create zip file $res\r\n");  
    }
    
    
    if (!$new_zip) {
        write_log("Could not find  $new_zip\r\n");  
        exit;
    		} 
    else {
        write_log("Found: $new_zip\r\n");
        }
    
    $zip = new ZipArchive;
    		
    $res = $zip->open($new_zip);
    if ($res === TRUE) {
      write_log("File $new_zip OPENED\r\n");
    	}
    else {
    	write_log("Could not open $new_zip\r\n Error # $res\r\n");
    	exit;
    	}
    
    if ($zip->extractTo($file_dir) === TRUE) {
      write_log("Extracted: $new_zip\r\n");
      $zip->close();
    	} 
    else {
      write_log("Extraction error\r\n");
      }
    
    $zipSS = $zip->getStatusString();		
    write_log("StatusString: $zipSS\r\n");
      
    
    $fin = $zip->close();
    if ($fin === TRUE) {
      write_log("Unzipped file to: $file_dir\r\n");
      } 
    else {
      write_log("Error on close: $fin \r\n");
    	exit;  
    	} 
    exit;
    And YES the file "aaa_new.zi p" does get created on
    my server.


    This is the log output:

    Class ZipArchive OK
    Created zip file: /home/gudfrt/public_html/stres/aaa_new.zip
    Found: /home/gudfrt/public_html/stres/aaa_new.zip
    File /home/gudfrt/public_html/stres/aaa_new.zip OPENED
    Extracted:/home/gudfrt/public_html/stres/aaa_new.zip
    StatusString:
    Error on close:

    Any ideas ?
  • Atli
    Recognized Expert Expert
    • Nov 2006
    • 5062

    #2
    Hey.

    A couple of things you should check out.
    • On lines #14 - #18, instead of testing whether the close() method returns true, check whether the addFromString() method returns true. - The way you have it now it doesn't really verify that the data was added to the zip, only that the zip object was closed properly. (Same goes for lines #60 - #68)
    • Line #29. That IF statement doesn't really verify that the file was created, it only verifies that the variable containing the location exists and is not empty. - You should use something like file_exists() to check if the file actually exists.
    • On line #50 you close the $zip object. Which means that if the zip is extracted OK, the code on lines #60 - #68 always return that there was an error; the $zip is already closed, so checking if it can be closed again will fail. - I would recommend just removing lines #60 - #68 altogether. Line #48 already checks whether the file was extracted or not. They are kind of redundant.

    Comment

    • numberwhun
      Recognized Expert Moderator Specialist
      • May 2007
      • 3467

      #3
      My recommendation would be to implement the use of "$php_errormsg".

      You can test it immediately after you do something like the close and see if it is populated with an error message. If so, print it out.

      Try using that and see if you can determine why the error printed out.

      Regards,

      Jeff

      Comment

      • jeddiki
        Contributor
        • Jan 2009
        • 290

        #4
        Thanks to both of you for your advice :)

        Although these situations are a real pain, I usually learn something new and useful :)

        I made the change to my php.ini file so I can use
        $php_errormsg. I will write it to my log file.

        At the same time I specified a text fle for php to
        write errors to:

        ; Log errors to specified file.
        error_log = my_new_log_file _path./errorlog.txt

        I think that will help.

        Errors are recorded in my server log, but this will be quicker to look at.

        I am continuing to work on the problem ...

        BTW - I noticed that I am on PHP version 5.2.10
        which is odd because I thought I was on 5.2.9
        I checked it two weeks ago.

        I don't know how it got updated !!!

        Comment

        • jeddiki
          Contributor
          • Jan 2009
          • 290

          #5
          OK - I have incorporated the suggestions from
          both Atli and numberwhun ( thanks again ! )

          Here is the new script. (below )

          Unfortunately, I can not see all the wonderful
          error catching code in action because the script insists on working !

          My log shows this:

          New record - Time Stamp: 01:00:15 Tuesday, 2 March 2010
          This script: sys/auto_cb_update. php, This file: /home/guru54gt5/public_html/sys/a_log_cb_update .txt
          Class ZipArchive OK
          Added zip info: /home/guru54gt5/public_html/sys/aaa_new.zip
          Created zip file: /home/guru54gt5/public_html/sys/aaa_new.zip
          Found: /home/guru54gt5/public_html/sys/aaa_new.zip Size: 140
          File /home/guru54gt5/public_html/sys/aaa_new.zip OPENED
          Extracted: /home/guru54gt5/public_html/sys/aaa_new.zip
          StatusString: No error
          Unzipped file to: /home/guru54gt5/public_html/sys/

          BUT I do have a question .. I do not seem to have given
          the script a file name for the extracted data to be stored in.

          So although it is Extracted - where would it put it ?

          I give it the zip file name but I don't think I gave it a file name
          inside the zip - I just added some data.

          Where in my script should I be giving the file name ?


          Here is the script with the changes made.


          Code:
          $new_zip = $file_dir.'aaa_new.zip';
          
          if (!class_exists('ZipArchive')) {
             write_log("Class ZipArchive not found\r\n"); 
             exit;
          	 } 
          else {
            write_log("Class ZipArchive OK\r\n"); 
            $zip = new ZipArchive;
          }
          
          $res = $zip->open($new_zip, ZipArchive::CREATE);
          if ($res === TRUE) {
            $add = $zip->addFromString('data1.txt', 'file content goes here');
            if ($add === TRUE) {
               write_log("Added zip info: $new_zip\r\n");
          		 }
          	else {
               write_log("Error on close: $add \r\n Error: $php_errormsg \r\n");
          	   exit;  
          		 }   
            $fin = $zip->close();
          	if ($fin === TRUE) {
               write_log("Created zip file: $new_zip\r\n");
               } 
            else {
              write_log("Error on close: $fin \r\n Error: $php_errormsg \r\n");
          	  exit;  
          	  }   
            }
          else {
              write_log("Could NOT Create zip file $res\r\n Error: $php_errormsg \r\n");
          }
          
          
          if(file_exists($new_zip)) {
            $fsz = filesize($new_zip);
          	 write_log("Found: $new_zip Size: $fsz\r\n");
            }
          else {
             write_log("Could not find $new_zip\r\n Error: $php_errormsg \r\n");
              }
          
          $zip = new ZipArchive;
          		
          $res = $zip->open($new_zip);
          if ($res === TRUE) {
            write_log("File $new_zip OPENED\r\n");
          	}
          else {
          	write_log("Could not open $new_zip\r\n Error # $res\r\n Error: $php_errormsg \r\n");
          	exit;
          	}
          
          if ($zip->extractTo($file_dir) === TRUE) {
            write_log("Extracted: $new_zip\r\n");
          	} 
          else {
            write_log("Extraction error\r\n Error: $php_errormsg \r\n");
            }
          
          $zipSS = $zip->getStatusString();		
          write_log("StatusString: $zipSS\r\n");
            
          $fin = $zip->close();
          if ($fin === TRUE) {
            write_log("Unzipped file to: $file_dir\r\n");
            } 
          else {
            write_log("Error on close: $fin \r\n Error: $php_errormsg \r\n");
          	exit;  
          	} 
          
          exit;
          Any suggestions accepted ! :)


          .

          Comment

          • jeddiki
            Contributor
            • Jan 2009
            • 290

            #6
            I have applied all the suggestions and yet
            my script that used to work every day now doesn't work.

            I have even gone and downloaded a backup of the script from a week ago
            and ran that .. it failed with the same error ( and yet the log for that day
            showed that it succeeded at that time).

            Now I have noticed something interesting.

            If I break the script into two parts and do the download first. then exit.
            Then afterwards, if I run the ZipArchive on the downloaded file, then it will work.

            It just won't work if I run the commands in the same script.
            (even though it did it fine before last Friday ).

            I do an fclose() on the file handle , so it should be OK

            Maybe I have not done it properly ?

            This is my code:
            Code:
            $file_dir = '/home/mysite/public_html/sys/';
            $file_zip = $file_dir.'a_zip_file.zip'; 
            
            $target_url = "https://example.com/get_xml_zip.php";
            $userAgent = 'EasyDL/3.xx';
            $cef = "curl_err_pdc.txt"; 
            $ceh = fopen($cef, 'w');
            
            write_log("Target_url: $target_url\r\n");
            
            // make the cURL request to $target_url
            $ch = curl_init();
            $fp = fopen("$file_zip", "wb");
            
            if ($fp === FALSE ) { 
              write_log("Problem opening $file_zip\r\n");
            	exit;
            }
            
            curl_setopt($ch, CURLOPT_USERAGENT, $userAgent);
            curl_setopt($ch, CURLOPT_URL,$target_url);
            curl_setopt($ch, CURLOPT_FAILONERROR, true);
            curl_setopt($ch, CURLOPT_STDERR, $ceh);		
            curl_setopt($ch, CURLOPT_VERBOSE, 1);
            curl_setopt($ch, CURLOPT_HEADER,0); 
            curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
            curl_setopt($ch, CURLOPT_AUTOREFERER, true);
            curl_setopt($ch, CURLOPT_BINARYTRANSFER,true);
            curl_setopt($ch, CURLOPT_TIMEOUT, 60);
            curl_setopt($ch, CURLOPT_FILE, $fp);
            
            $output = curl_exec($ch);
            $info = curl_getinfo($ch);
            
            if ($output === FALSE || $info['http_code'] != 200) {
              write_log("No cURL data returned for $target_url [". $info['http_code']. "]\r\n ");
              if (curl_error($ch)) write_log($output."CURL error number: curl_errno($ch)\r\n CURL error: curl_error($ch)\r\n");
            	exit;
              }
            else {
              write_log("CURL completed successfully.\r\n");
            	}
            
            curl_close($ch);
            
            fclose($fp);
            fclose($ceh);
            
            
            //  IF I SPLIT HERE, IT WORKS
            
            
            if(file_exists($file_zip)) {
              $fsz = filesize($file_zip);
            	 write_log("Found: $file_zip Size: $fsz\r\n");
              }
            else {
              write_log("Could not find $file_zip\r\n Error: $php_errormsg");
              }
            
            if (!class_exists('ZipArchive')) {
               write_log("Class ZipArchive not found\r\n"); 
               exit;
            	 } 
            else {
              write_log("Class ZipArchive OK\r\n"); 
              $zip = new ZipArchive;
            }
            	
            $res = $zip->open($file_zip);
            if ($res === TRUE) {
              write_log("File $file_zip OPENED\r\n");
            	}
            else {
            	write_log("Could not open $file_zip \r\n Error # $res\r\n Error: $php_errormsg");
            	exit;
            	}
            
            $extrt = $zip->extractTo($file_dir);
            if ( $extrt === TRUE) {
              write_log("Extracted: $file_zip\r\n");
            	} 
            else {
              write_log("Extraction error: $extrt\r\n Error: $php_errormsg");
              }
            
            $zipSS = $zip->getStatusString();		
            write_log("StatusString: $zipSS\r\n");
              
            $fin = $zip->close();
            if ($fin === TRUE) {
              write_log("Unzipped file to: $file_dir\r\n");
              } 
            else {
              write_log("Error on close: $fin \r\n");
            	exit;  
            	}

            When I try and run this in one go I get this output:

            CURL completed successfully.
            Found: '/home/mysite/public_html/sys/a_zip_file.zip Size: 282624
            Class ZipArchive OK
            Could not open /home/mysite/public_html/sys/a_zip_file.zip
            Error # 19
            Error:
            BUT if I split the script after the download it will work.

            I mean BOTH parts will work, the downlaod AND the Zip Extraction.

            Can anyone see where I have gone wrong ?


            .

            Comment

            • Atli
              Recognized Expert Expert
              • Nov 2006
              • 5062

              #7
              Ok, if both parts work separately, then it is fair to assume the problem isn't in the code itself. - Try to add a sleep(1) call between the two parts. See if that does anything. Perhaps the OS is trying to move the file, or something, that is causing a delay in the file being created and it being available for usage.

              If not, try to figure out exactly why the file is failing to open. Do something like:
              [code=php]<?php
              $zip = new ZipArchive;
              $res = $zip->open('test.zip ');
              if ($res === TRUE)
              {
              echo 'ok';
              $zip->extractTo('tes t');
              $zip->close();
              }
              else
              {
              $error_values = array
              (
              ZIPARCHIVE::ER_ EXISTS => 'ER_EXISTS',
              ZIPARCHIVE::ER_ INCONS => 'ER_INCONS',
              ZIPARCHIVE::ER_ INVAL => 'ER_INVAL',
              ZIPARCHIVE::ER_ MEMORY => 'ER_MEMORY',
              ZIPARCHIVE::ER_ NOENT => 'ER_NOENT',
              ZIPARCHIVE::ER_ NOZIP => 'ER_NOZIP',
              ZIPARCHIVE::ER_ OPEN => 'ER_OPEN',
              ZIPARCHIVE::ER_ READ => 'ER_READ',
              ZIPARCHIVE::ER_ SEEK => 'ER_SEEK'
              );
              echo 'failed, code: ' . $error_values[$res];
              }
              ?>[/code]
              That will at last tell you why this is happening.

              Comment

              • Atli
                Recognized Expert Expert
                • Nov 2006
                • 5062

                #8
                One idea, though...

                Try the following:
                [code=php]
                // Comment out this line (#30)
                #curl_setopt($c h, CURLOPT_FILE, $fp);

                // Add this Curl option
                curl_setopt($ch , CURLOPT_RETURNT RANSFER, true);

                // Add this after line #41
                fwrite($fp, $output, strlen($output) );
                [/code]
                This, rather than having Curl write the data to the file, has Curl return the data to PHP, which then writes the file the "old-fashion" way.

                Comment

                • jeddiki
                  Contributor
                  • Jan 2009
                  • 290

                  #9
                  Hi again.

                  I am going to do what you suggest, just to see what it says but
                  during that last hour I have been looking through my logs (yum log)
                  and I found that on 27th my php version changed to php-5.2.10

                  That co-incides with the last date my script ran properly.

                  I have also found a file path bug report for php-5.2.10

                  I updated recently to php-5.2.10 and some scripts are not working anymore. The scripts added some elements to the include_path. While including some files from the include_path php echos the error that it cannot resolve the host name. I think that this error is caused by the change, that stream wrappers could be used in the include path and the PATH_SEPERATOR and the stream wrappers collidate.

                  Downgrading to php-5.2.9-r2 solves the problem again.
                  So I think I will downgrade and see if that fixes it !

                  I will also make sure any "automatic" updates to php are turned off cos I didn't do the update !!

                  Although I have learned a bit more about error testing, - I lost three/four days of forward movement on my project because of this !

                  Thanks for your help, I appreciate your insights :)


                  Added:

                  OK ran that change and I got this output:

                  Class ZipArchive OK
                  Could not open /home/guru54gt5/public_html/sys/a_zip_file.zip
                  Error # 19
                  Error:
                  Failed, code: ER_NOZIP

                  Comment

                  Working...