In my article today, I will show you how you can upload both single and multiple files in PHP and save them in a zip file.
I will make use of the ZipArchive()
class in PHP for the purpose of this tutorial.
INTRODUCTION
The ZipArchive()
class is an inbuilt class in PHP that can be used to archive a file or group of files and compress it with zip.
Now let me show you how you can use this class to upload and zip both single and multiple files.
ABOUT THE CLASS
In order to use this class in your project, you must initialize it using the new
keyword
//initialize the zip archive class
$zip = new ZipArchive()
Once you have initialized it, the methods below become available for use
- open
This method opens an existing zip archive for reading, writing, or modifying or creates an empty zip archive.
- addFile
This method adds a file from a given path to a ZIP archive.
- close
This method closes opened or created archives and then saves changes.
Now let us go ahead and understand how we can upload and zip both single and multiple files in PHP
UPLOADING A SINGLE FILE
Assuming I have an HTML form that allows users to upload a single file like this;
<form method="post" action="" enctype="multipart/form-data">
<input type="file" name="file">
<button type="submit">Submit</button>
</form>
In PHP, I will check if a file was uploaded using the POST
method, then I will process the file, create a new Zip Archive, and add the file to the zip archive.
Now let us talk about what happens when we upload a file.
What Happens When We Upload A File
When we upload a file, its properties become available to the $_FILES
global variable.
The $_FILES
global variable is an associative array of items uploaded to the current script via the HTTP POST method.
This means that we can see properties like;
- The name of the file
[name]
. - The type of file
[type]
. - The temporary location of the file
[tmp_name]
. - The error code
[error]
. - The size of the file (in bytes)
[size]
.
This is an example of a typical output from the $_FILES
array when a single file is uploaded.
So we can see that the index tmp_name
contains the path of the uploaded file which is also its temporary location in the server.
Now let us create a script that will process the incoming file and save it to an archive.
//check if the request method is POST
if($_SERVER['REQUEST_METHOD'] === 'POST'){
//check if a file was uploaded
if(isset($_FILES['file']) && !empty($_FILES['file']) && !is_array($_FILES['file'])){
//initialize the ziparchive class
$zip = new ZipArchive();
//set the name of our zip archive
$zip_file_name = 'MyFile.zip';
//create the new zip archive using the $file_name above
if($zip->open($zip_file_name, ZipArchive::CREATE) === true){
//add the file to the archive
$zip->addFile($_FILES['file']['tmp_name'], $_FILES['file']['name']);
//close the archive
$zip->close();
}else{
echo "Couldn't create Zip Archive";
}
}
}
If you look at the snippet above, you will notice that we followed a very simple order while creating our zip archive.
First, we created a new zip archive with the name MyFile.zip
using the open()
method.
Then we added the file coming from the $_FILES
array using the addFile()
method and lastly, we closed the archive so that it will save our changes using the close()
method.
if you should run this code in your local development server and upload a file, you will see the zip archive MyFile.zip
right within the root of your folder. Open this archive and you will see the file you just uploaded.
Now let us talk about how we can upload and zip multiple files
UPLOADING MULTIPLE FILES
Uploading multiple files and saving them in a zip file is not too different from the script above.
Let us modify the HTML form responsible for uploading multiple files like so;
<form method="post" action="" enctype="multipart/form-data">
<input type="file" name="file[]" multiple>
<button type="submit">Submit</button>
</form>
Before we go into detail, let us see the output of the $_FILES
array when we upload multiple files.
At this point, you may be confused about how to retrieve the file path and names of each of the files, and how to add them to an archive.
Well, you don't have to be confused because we will loop through the $_FILES array, then match the file tmp_names and file names based on their indexes.
//check if the request method is post
if($_SERVER['REQUEST_METHOD'] === 'POST'){
//check if a file was uploaded
if(isset($_FILES['file']) && !empty($_FILES['file']) && is_array($_FILES['file'])){
//initialize the ziparchive class
$zip = new ZipArchive();
//set the name of our zip archive
$zip_file_name = 'MyFile.zip';
//create the new zip archive using the $file_name above
if($zip->open($zip_file_name, ZipArchive::CREATE) === true){
//loop through the tmp_name of the files in $_FILES array
foreach($_FILES['file']['tmp_name'] as $key => $tmpName){
//get the name of the file
$file_name = $_FILES['file']['name'][$key];
//add the file
$zip->addFile($tmpName, $file_name);
}
//close the archive
$zip->close();
}else{
echo "Couldn't create Zip Archive";
}
}
}
Now if you should run this code in your local development server and upload some files, you will notice that the archive is updated with the recent files you just uploaded.
You can easily group the logic to handle both single and multiple file uploads.
//check if request method is post
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
//check if a file was uploaded
if (isset($_FILES['file']) && !empty($_FILES['file'])) {
//single file upload
if (!is_array($_FILES['file'])) {
//initialize the ziparchive class
$zip = new ZipArchive();
//set the name of our zip archive
$zip_file_name = 'MyFile.zip';
//create the new zip archive using the $file_name above
if ($zip->open($zip_file_name, ZipArchive::CREATE) === true) {
//add the file to the archive
$zip->addFile($_FILES['file']['tmp_name'], $_FILES['file']['name']);
//close the archive
$zip->close();
} else {
echo "Couldn't create Zip Archive";
}
}
//multiple file uploads
elseif (is_array($_FILES['file'])) {
//initialize the ziparchive class
$zip = new ZipArchive();
//set the name of our zip archive
$zip_file_name = 'MyFile.zip';
//create the new zip archive using the $file_name above
if ($zip->open($zip_file_name, ZipArchive::CREATE) === true) {
//loop through the tmp_name of the files in $_FILES array
foreach ($_FILES['file']['tmp_name'] as $key => $tmpName) {
//the name of the file
$file_name = $_FILES['file']['name'][$key];
//add the file
$zip->addFile($tmpName, $file_name);
}
//close the archive
$zip->close();
} else {
echo "Couldn't create Zip Archive";
}
}
}
}
If in your application, users are allowed to upload multiple files that are archived and compressed as zip, you need to make sure that you generate a unique name for the zip archives.
You can use PHP's inbuilt functions uniqid()
, rand()
to generate a random key for the zip archive name.
//generate a random key for the zip archive name
$randKey = uniqid().rand(0000,9999);
//zip file name
$zip_file_name = "$randKey.zip";
CONCLUSION
We have talked about the ZipArchive
class in PHP, its methods, and how we can use it to create an archive of files and compress them as zip.
We also talked about what happens when we upload a file and how we can extract the name of an uploaded file, its size, and its temporary location from the $_FILES
array.
I also showed you the output of the $_FILES
array in case of a single or multiple file upload.
Finally, I gave you a hint on how you can generate a random key for your zip archive names if you are zipping the files uploaded by users.
EXTRA
I have developed a validation library that helps to validate your forms in PHP using validation rules, sophisticated regular expressions, and PHP's inbuilt validation.
This Library is Open-source and you can use this library to validate data coming from the $_POST
, $_GET
, or $_FILES
arrays.
Check out the documentation of this library below
Thank you for reading.
Image Credit: Henry & Co on Unsplash
Top comments (0)