May
20
2010

How to Upload and Unpack a Zip File using PHP

by   |  Posted in Tutorials  |  20 comments

When you’re emailing or uploading larger files, it always makes sense to compress them first. This decreases file size and also helps avoid file corruption during transfer. The most common compressed file you will encounter is the zip file, since most operating systems come with a basic utility to quickly zip and unzip files. Creating a small function to upload a zip file to your server and unpack in the process isn’t as complicated as you might think.

First let’s create a simple form that will allow us to browse our computer and upload a zip file.

<form enctype="multipart/form-data" method="post" action="">
<label>Choose a zip file to upload: <input type="file" name="zip_file" /></label>
<br />
<input type="submit" name="submit" value="Upload" />
</form>

Now comes the uploader function:

<?php
if($_FILES["zip_file"]["name"]) {
	$filename = $_FILES["zip_file"]["name"];
	$source = $_FILES["zip_file"]["tmp_name"];
	$type = $_FILES["zip_file"]["type"];
 
	$name = explode(".", $filename);
	$accepted_types = array('application/zip', 'application/x-zip-compressed', 'multipart/x-zip', 'application/x-compressed');
	foreach($accepted_types as $mime_type) {
		if($mime_type == $type) {
			$okay = true;
			break;
		} 
	}
 
	$continue = strtolower($name[1]) == 'zip' ? true : false;
	if(!$continue) {
		$message = "The file you are trying to upload is not a .zip file. Please try again.";
	}
 
	$target_path = "/home/var/yoursite/httpdocs/".$filename;  // change this to the correct site path
	if(move_uploaded_file($source, $target_path)) {
		$zip = new ZipArchive();
		$x = $zip->open($target_path);
		if ($x === true) {
			$zip->extractTo("/home/var/yoursite/httpdocs/"); // change this to the correct site path
			$zip->close();
 
			unlink($target_path);
		}
		$message = "Your .zip file was uploaded and unpacked.";
	} else {	
		$message = "There was a problem with the upload. Please try again.";
	}
}
?>

To make sure the success and error messages appear, we will also have to add to short pieces of PHP code:

<?php if($message) echo "<p>$message</p>"; ?>

Putting it all together into a PHP file would look like this:

<?php
if($_FILES["zip_file"]["name"]) {
	$filename = $_FILES["zip_file"]["name"];
	$source = $_FILES["zip_file"]["tmp_name"];
	$type = $_FILES["zip_file"]["type"];
 
	$name = explode(".", $filename);
	$accepted_types = array('application/zip', 'application/x-zip-compressed', 'multipart/x-zip', 'application/x-compressed');
	foreach($accepted_types as $mime_type) {
		if($mime_type == $type) {
			$okay = true;
			break;
		} 
	}
 
	$continue = strtolower($name[1]) == 'zip' ? true : false;
	if(!$continue) {
		$message = "The file you are trying to upload is not a .zip file. Please try again.";
	}
 
	$target_path = "/home/var/yoursite/httpdocs/".$filename;  // change this to the correct site path
	if(move_uploaded_file($source, $target_path)) {
		$zip = new ZipArchive();
		$x = $zip->open($target_path);
		if ($x === true) {
			$zip->extractTo("/home/var/yoursite/httpdocs/"); // change this to the correct site path
			$zip->close();
 
			unlink($target_path);
		}
		$message = "Your .zip file was uploaded and unpacked.";
	} else {	
		$message = "There was a problem with the upload. Please try again.";
	}
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Untitled Document</title>
</head>
 
<body>
<?php if($message) echo "<p>$message</p>"; ?>
<form enctype="multipart/form-data" method="post" action="">
<label>Choose a zip file to upload: <input type="file" name="zip_file" /></label>
<br />
<input type="submit" name="submit" value="Upload" />
</form>
</body>
</html>

Zip File Icon: Ritesh Ranjan

About the author:

A freelance web developer living in Montreal who spends most of his time writing for this site and building Premium themes for WordPress. You can find him on Twitter @bavotasan.

Site5 Affiliate Link
If you liked this, please share it.

Tags: , , , , , , , , ,

Short URL: http://bit.ly/d2GGGv

Discussion 20 Comments

  1. Dragan on May 21, 2010 at 2:21 pm

    Hi, great tutorial, thank you.

    When I open the page in the browser I get this error: Notice: Undefined index: zip_file in /home/www/xxx.php on line 525.

    How I can solve this.
    Regards

  2. Dragan on May 21, 2010 at 2:34 pm

    Hi, just to give you complete information, the line 525 is

    if($_FILES["zip_file"]["name"]) {

    Thank you in advance
    Regards

  3. Naveen Sridhara on July 16, 2010 at 8:58 am

    nice program this is working i like this, and thanks for your code

    There is a very small error in line 18 in then last box, semicolon is missing.

    i need the reverse of this program can you plz help me.
    i need to upload a file that need to be change a zip and store in a folder for downloading.

    • c.bavota on July 16, 2010 at 10:55 am

      Thanks. Fixed the error. Why don’t you just upload it as a zip file?

  4. Andy on August 6, 2010 at 7:52 pm

    I don’t see where you defined a ZipArchive() class…? As seen in $zip = new ZipArchive();

  5. Corbin on February 4, 2011 at 12:55 pm

    Nicely done. I’ve got it set up and it’s working fine. One problem I’m running into is a duplicate version of the zip file is uploaded as well. So, there are two new directories… One is the name of the zip file and the other is titled _MACOSX and contains the duplicate copy of the first directory. Any thoughts?

    • c.bavota on February 4, 2011 at 5:46 pm

      Yup. That is due to the fact that you created your zip file using the Mac compless tool. It also stores some meta data about the archive. I use YemuZip on my Mac to create PC compatible zip files. Doing it this way will eliminate that _MACOSX directory.

      Or, you could create a function which checks for that _MACOSX directory and deletes it if it exists.

  6. Aroet Uddhav on February 7, 2011 at 5:15 am

    Thanks for the code !….good 1..!

  7. Bytes Land on February 8, 2011 at 3:33 am

    Please help me, I am getting following error:
    Warning: chdir() [function.chdir]: open_basedir restriction in effect. File() is not within the allowed path(s): (/home/:/usr/lib/php:/tmp) in /home/a9030732/public_html/upload/index.php on line 249
    have no idea what I was doing wrong(

  8. Celeste S. on February 21, 2011 at 5:19 pm

    I appear to be having a lot of the same issues as Bytes Land. The same message seems to pop up whenever I attempt to implement the Uploading Function. Am I perhaps doing something wrong? Do you know of any common issues that you think can be alleviated? I often work with coding with

    Warning: chdir() [function.chdir]: open_basedir restriction in effect. File() is not within the allowed path(s): (/home/:/usr/lib/php:/tmp) in /home/a9030732/public_html/upload/index.php on line 249

    So I don’t know really know if I’m doing anything wrong.

    Thanks a bunch!!! :)

    • c.bavota on February 22, 2011 at 11:26 am

      The error is due to the fact that you are running your PHP in safe mode and open_basedir protection is enabled as a security measure to prevent users from opening files or scripts located outside of their home directory.

  9. chagi on March 15, 2011 at 3:41 am

    GREAT!!!!!! THANK YOU SOOO MCH!!!!

  10. chagi on March 15, 2011 at 7:30 am

    can’t i upload it without extracting?

    • c.bavota on March 15, 2011 at 9:59 am

      If you don’t want to extract it you can just upload it the same way you would any file.

  11. Vinny on March 23, 2011 at 9:06 am

    This Worked For Me:

    &lt;?php
     
    if($_FILES[&quot;zip_file&quot;][&quot;name&quot;]) {
    	$filename = $_FILES[&quot;zip_file&quot;][&quot;name&quot;];
    	$source = $_FILES[&quot;zip_file&quot;][&quot;tmp_name&quot;];
    	$type = $_FILES[&quot;zip_file&quot;][&quot;type&quot;];
     
    	$name = explode(&quot;.&quot;, $filename);
    	$accepted_types = array(&#039;application/zip&#039;, &#039;application/x-zip-compressed&#039;, &#039;multipart/x-zip&#039;, &#039;application/x-compressed&#039;);
    	foreach($accepted_types as $mime_type) {
    		if($mime_type == $type) {
    			$okay = true;
    			break;
    		} 
    	}
     
    	$continue = strtolower($name[1]) == &#039;zip&#039; ? true : false;
    	if(!$continue) {
    		$message = &quot;The file you are trying to upload is not a .zip file. Please try again.";
    	}else{
    		$target_path = "/var/www/uploads/".$filename;  // change this to the correct site path
    		if(move_uploaded_file($source, $target_path)) {
    			$zip = new ZipArchive();
    			$x = $zip-&gt;open($target_path);
    			if ($x === true) {
    				$zip-&gt;extractTo("/var/www/uploads/"); // change this to the correct site path
    				$zip-&gt;close();
     
    				unlink($target_path);
    			}
    			$message = "Your .zip file was uploaded.";
    		} else {	
    			$message = "There was a problem with the upload. Please try again.";
    		}
    	}
    }
     
    ?&gt;
     
     
     
    	function changed() {
    		var item = $("#file").val().split("\\");
    		var itemLen = item.length-1;
     
    		$("#selFile").html( "Selected File: " + item[itemLen] );
     
    	}
     
     
     
    body {
    	font-size: 12px;
    	font-family: sans;
    }
     
    input[type=file] {
    	width: 86px;
    }
     
    .error {
    	border: 1px solid red;
    	background: pink;
    	color: red;
    	-webkit-border-radius: 6px;
    	-webkit-box-shadow: 0 0 5px black;
    	position: fixed;
    	top: 10px;
    	left: 5%;
    	width: 90%;
    	padding: 2px 5px;
    	text-align: center;
    }
     
    .done {
    	border: 1px solid green;
    	background: lightgreen;
    	color: green;
    	-webkit-border-radius: 6px;
    	-webkit-box-shadow: 0 0 5px black;
    	position: fixed;
    	top: 10px;
    	left: 5%;
    	width: 90%;
    	padding: 2px 5px;
    	text-align: center;
    }
     
    .panel {
    	border: 1px solid black;
    	background: silver;
    	color: black;
    	-webkit-border-radius: 6px;
    	-webkit-box-shadow: 0 0 5px black;
    	position: fixed;
    	top: 50%;
    	left: 50%;
    	width: 300px;
    	height: 150px;
    	margin-top: -75px;
    	margin-left: -150px;
    	padding: 2px 5px;
    	text-align: center;
    }
     
     
    .Zip Uploader
     
    &lt;?php if($message) echo &quot;$message"; ?&gt;
     
     
     
    	Choose a zip file to upload:

    @chagi – remove these lines:

    $zip = new ZipArchive();
    $x = $zip-&gt;open($target_path);
    if ($x === true) {
    $zip-&gt;extractTo("/home/var/yoursite/httpdocs/"); // change this to the correct site path
    $zip-&gt;close();
  12. Vinny on March 23, 2011 at 9:08 am

    okay the top code failed… but the main part of it didn’t

  13. Fantasy Writer on April 29, 2011 at 10:27 pm

    Thanks for this useful code. It took me an hour to figure out that I was running PHP in safe mode, though. I should have read through the comments earlier. :)

    • Marc on May 10, 2011 at 12:32 am

      @Vinny I tried to manipulate the top code you posted, but did not come up with any solutions. Were you able to fix it? I’ve just recently started using PHP, so my ambition may be running a few lengths ahead of my knowledge, but I have an additional question. Hopefully, it will make sense.

      A response to a comment above recommended turning off safe mode as well as disabling open_basedir protection in order to have things work smoothly. I’m hoping to come across availability solutions that will remedy the issue. What sort of security functionality will I lose by doing this? Are there recommended manipulations that I can perform on open_basedir protection, or is it just “on/off”? Thanks for any help. Marc

  14. GG on May 23, 2011 at 4:19 pm

    Hi thanks so much for this post it is great! I had a question, any help would be grateful as I am still new at php. The uploading of a zip file and the decompressing of the file works great, but I can upload ANY file, not just zip files with this coding. Am I missing something? I am using the identical code.

    Thanks in advance.

    • c.bavota on May 25, 2011 at 4:07 pm

      There is a code check to make sure it is a zip file. If not, the code exits.