Solved

Extract process with ZipArchive Slow in php

Posted on 2013-07-01
17
783 Views
Last Modified: 2013-11-19
Hello Experts Exchange!

I'm fairly new to php so please be gentle!

Once a day, I receive a .zip file to my ftp account and I would like to build a script that unzips the file into the current directory. The code that I'm using is below.

$zip = new ZipArchive;    
$res = $zip->open($filename);

if ($res === TRUE) {
	$zip->extractTo('./');	
	echo 'Unzip was successful';
} else {
	echo 'Unzip was not successful';
	die();
}

$zip->close();

Open in new window


The problem I'm running into is my execution time. Every time I run the script, it times out. I've used set_time_limit(300); and the script still times out and the file I'm trying to unzip is only 50,437 B. Is there something amiss in my code or is there a faster alternative to ZipArchive?

I'm running PHP Version 5.3.6.
0
Comment
Question by:danswill
  • 9
  • 8
17 Comments
 
LVL 34

Expert Comment

by:gr8gonzo
ID: 39291278
It's probably not that bit of code that is causing the problem. If there are errors in the script, it will usually just abort right away and tell you about the error. What's the rest of the code look like?
0
 
LVL 34

Expert Comment

by:gr8gonzo
ID: 39291291
Most timeouts are due to either:

1. Infinite loops:
$somecondition = true;
while($somecondition)
{
   ... code that never changes $somecondition to false ...
}

2. Network timeouts:
Connecting to a database, FTP server, or other remote resource improperly or in a way that does not get through security properly.

3. Slow or nested database queries:
$rs = mysql_query("SELECT ton, of, data FROM atable");

or

$rs1 = mysql_query("SELECT ten,thousand,rows FROM tableA");
while($row1 = mysql_fetch_assoc($rs1))
{
  $rs2 = mysql_query("SELECT something FROM tableB WHERE some_criteria=".$row1["bit_of_data"]);
  ... etc ...
}

See if your code has any of those types of connections (I'm banking on the FTP connection timing out).
0
 

Author Comment

by:danswill
ID: 39291420
Thank you for your comments! I ran a test with a dummy.zip that's only 1,789 B (compared to the original file which is 50,437 B) and it ran just fine.

Since it seems that network timeouts is the real issue, how do I go about solving this? Do I need to make changes to my ftp server?
0
 
LVL 34

Expert Comment

by:gr8gonzo
ID: 39291446
I'm not sure I understand. You said dummy.zip works just fine, but the original file doesn't, so I'm not sure why it would be a network timeout. Unless you are trying to download the original file from the FTP server using PHP immediately before unzipping it. If so, what does your code look like? (Just erase or change any sensitive info like host names, user names, and passwords).
0
 

Author Comment

by:danswill
ID: 39291479
Hello again,

The original file is 50,437 B and the dummy.zip is 1,789 B. Since the original file is 10 times larger, I was assuming this was causing the issue.

The file is located as the same location as the script, so I'm not connecting to a ftp site. Below is the my entire code, nothing fancy.

ftp screenshot

$filename = "dummy.zip";
$zip = new ZipArchive;    
$res = $zip->open($filename);

if ($res === TRUE) {
	$zip->extractTo('./');	
	echo 'Unzip was successful';
} else {
	echo 'Unzip was not successful';
	die();
}

$zip->close();

print('Unzipping process was successful.');

Open in new window

0
 
LVL 34

Expert Comment

by:gr8gonzo
ID: 39291512
No, there should not be any problem with a 50k file. That is a very small file and PHP should be able to unzip that in less than a second.

If those 15 lines are truly ALL of the code that you have (and I mean everything - not excluding code that you think is not relevant), then I'm not quite sure what to tell you except that you should check your error logs. There's no reason ZipArchive should take any longer than milliseconds to open and extract a 50k file.

When you say that it times out, what are the final results that you see? Do you see a PHP error message about it?
0
 

Author Comment

by:danswill
ID: 39293279
Hello again,

Below is the full source code of my file. The only thing I've left out is a couple of variables.

Here's the error that I see when I run the script.

Fatal error: Maximum execution time of 300 seconds exceeded in /home/tucker15/public_html/sierrainteractive/openhouses.php on line 14

$year = date(Y);
$month = date(m);
$day = date(d);

$filename = "144-FCTUCKERINDI-". $year . $month . $day . "-44619.zip";

$zip = new ZipArchive;    
$res = $zip->open($filename);

if ($res === TRUE) {
	$zip->extractTo('./');	
	echo 'Unzip was successful';
} else {
	echo 'Unzip was not successful';
	die();
}

$zip->close();

print('Unzipping process was successful.');

Open in new window

0
 
LVL 34

Expert Comment

by:gr8gonzo
ID: 39293311
Hmmm... so the error is on line 14, but in the code above, line 14 is an echo statement. If you add a blank line above the echo, like:

} else {

echo 'Unzip was not....';
Does the error change to line 15?

On a side note, always put quotes around strings:

date("Y") or date('Y') but not date(Y)

Otherwise, you're forcing PHP to look for a constant called Y before it gives up and tries to assume that you meant a string. It will also throw a warning that it can't find a variable called Y so it assumes you meant "Y".

(The quoted string thing is not the problem here, but it's good programming practice.)
0
What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 

Author Comment

by:danswill
ID: 39293395
Hello,

I'm really sorry, I didn't include the opening php tag and a couple of comment lines at the beginning of the script. It seems the culprit is really $zip->extractTo('./'); as seen in the following message.

And thank you so much for the tips about the date.


Error Message
Fatal error: Maximum execution time of 300 seconds exceeded in /home/tucker15/public_html/sierrainteractive/openhouses.php on line 12

Code
<?php
$year = date("Y");
$month = date("m");
$day = date("d");

$filename = "144-FCTUCKERINDI-". $year . $month . $day . "-44619.zip";

$zip = new ZipArchive;    
$res = $zip->open($filename);

if ($res === TRUE) {
	$zip->extractTo('./');	
	echo 'Unzip was successful';
} else {
	echo 'Unzip was not successful';
	die();
}

$zip->close();

print('Unzipping process was successful.');

Open in new window

0
 
LVL 34

Expert Comment

by:gr8gonzo
ID: 39293447
Well, it's infrequent, but I would say that it's either a problem with your ZIP file or a bad install of the ZIP PECL extension. You could try updating the extension to whatever the latest version is to see if that fixes it, or you could use a variety of other classes to do it.

http://www.phpclasses.org/package/3864-PHP-Create-and-extract-ZIP-archives-in-purely-in-PHP.html

That package doesn't use the PECL extension and might give you a different result (if it's a bad file it might tell you rather than simply timing out).
0
 

Author Comment

by:danswill
ID: 39311368
Hello again, after a lot of searching, I found out that if I run 'unzip -tq filename' I could find out more information about the zip file. So, I ran this line of code and received the following message.

Caution: zero files tested in 144-FCTUCKERINDI-20130709-44619.zip. 1 file skipped because of unsupported compression or encoding.

This led to even more searching and I installed p7zip on my server, but it's still not working. The .zip file came from an asp.net environment.
0
 
LVL 34

Expert Comment

by:gr8gonzo
ID: 39311427
It sounds like the asp.net application didn't correctly create the ZIP file. Can you post the file here, or if not, open it up in a text editor and see if it actually looks like a binary ZIP file.
0
 

Author Comment

by:danswill
ID: 39311442
I can unzip the file without a problem on my Windows machine but not from the server. My file actually has some (semi) sensitive data. Is there a way I can email it just to you?
0
 
LVL 34

Accepted Solution

by:
gr8gonzo earned 500 total points
ID: 39311491
If it's sensitive (semi or not) data, then don't send it out to anyone, especially not over email (even though I can tell you that I'm trustworthy, you have no way to fully validate that).

That is bizarre that you could unzip it from Windows but not from any common utilities on the server. Almost every ZIP file uses the standard deflate algorithm, which should be supported everywhere. Usually when there is any difference, the built-in ZIP file support in Windows is the one that cannot open a ZIP file, not the other way around.

1. Are you 110% sure that the file is exactly the same on Windows as on the server? Do the md5 hashes match?

2. On the server, try running this command:
hexdump /path/to/your/zipfile.zip | head -n1

That should display the first 16 bytes of your ZIP file in hex, like this:
[root@server ~]# hexdump test.zip | head -n1
0000000    4b50 0403 0014 0000 0008 8213 4102 0a29

Open in new window


That line is broken down into:
0000000 - just the offset of the bytes you're looking at - not file data
4b50 0403 - the standard "hey, I'm a ZIP file!" signature (these 4 bytes should be the same across all standard ZIP files)
0014 - the 2-byte version of the application used to create the file
0000 - any special flags crammed into a 2-byte value
0008 - the compression used (0008 = deflate algorithm)

Can you show the output when you run the same hexdump on your file (the first 16 bytes will have nothing sensitive - it is all ZIP structure)?
0
 

Author Comment

by:danswill
ID: 39311606
1. Are you 110% sure that the file is exactly the same on Windows as on the server? Do the md5 hashes match?
Honestly, I'm not sure how to check the two. The file gets dropped onto our ftp site from our vendor.

2) Here's the output.
0000000 4b50 0403 002d 0000 0008 2015 42e9 cf7c
0
 

Author Comment

by:danswill
ID: 39311725
After even further search, I feel like I've been searching forever, this command now works in unzipping the file.

system('7za x filename');
0
 

Author Closing Comment

by:danswill
ID: 39311729
Although this was not the exact solution, this additional information led me to the correct solution of getting p7zip installed on my server and using system('7za x filename') to extract my zipped file.
0

Featured Post

Easy Project Management (No User Manual Required)

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
Joomla Website Malfunction 9 52
spacing 5 29
php mail headers 2 12
echo button 13 47
Part of the Global Positioning System A geocode (https://developers.google.com/maps/documentation/geocoding/) is the major subset of a GPS coordinate (http://en.wikipedia.org/wiki/Global_Positioning_System), the other parts being the altitude and t…
Read about why website design really matters in today's demanding market.
This video teaches users how to migrate an existing Wordpress website to a new domain.
This tutorial will teach you the core code needed to finalize the addition of a watermark to your image. The viewer will use a small PHP class to learn and create a watermark.

705 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now