Im unzipping a file, that I dont know the name of its contents. I need to immediately open and process this file. How can I grab it? without knowing its name?
Heres my code...
if($extension == 'ZIP' || $extension == 'zip'){
$zip = new ZipArchive;
$res = $zip->open($_FILES['my_file']['tmp_name']);
if ($res === TRUE) {
$zip->extractTo('../storage/unzipped/');
$zip->close();
// Get file, how? If I dont know the name, of the file inside the
// zip folder?
} else {
// Errors
}
}
I definitely know how to open the file, IF I know the name.....but in this case, I wont know the name, so I need to somehow get it. zip_entry_name()??
Ok well I solved it before anyone could answer...so here it is for anyone that needs it.
$entry = $zip->getNameIndex(0);
Or if your file has multiple folders/files
$filenames=[];
for ($i = 0; $i < $zip->numFiles; $i++) {
$filenames[] = $zip->getNameIndex($i);
};
Full code
if($extension == 'ZIP' || $extension == 'zip'){
$zip = new ZipArchive;
$res = $zip->open($_FILES['my_file']['tmp_name']);
if ($res === TRUE) {
$zip->extractTo('../storage/unzipped/');
$filename = $zip->getNameIndex(0);
// Open file or stream it or whatever you want
// now that you have the name
$zip->close();
} else {
// error
}
}
Related
I am trying to unzip an uploaded file and rename and upload it in my server
here is my code
PHP
$fname = md5(rand()).'.csv';
$full_path = Config::get('filesystems.disks.local.root');
$zip = new ZipArchive;
if ($zip->open($excel_file) === TRUE)
{
$zip->renameName($zip->getNameIndex(0),$fname);
$zip->extractTo($full_path. '/exceluploads/');
$zip->close();
} else {
return redirect()->back()->withErrors('File is not zipped');
}
But this is not working , I am sure I am doing some mistake since I am using the ZipArchive for the first time .
You are changing the zip file's content, so you need to specify what you want to extract.
<?php
$fname = md5(rand()).'.csv';
$full_path = Config::get('filesystems.disks.local.root');
$zip = new ZipArchive;
if ($zip->open($excel_file) === TRUE) {
$zip->renameName($zip->getNameIndex(0), $fname);
// Please notice the $fname, passed as a parameter for extractTo
$zip->extractTo($full_path . 'exceluploads/', $fname);
$zip->close();
} else {
return redirect()->back()->withErrors('File is not zipped');
}
The following code unzips my uploaded file and extracts everything in a directory called PDF. It then proceeds to iterate through the files and return files to download.
My problem is I need to check the file extension. I would only like to return the PDF file back to the user but some of the uploaded files have unnecessary images.
How can I check the contents of the file to ensure the unzipped file is a PDF & only the PDF is returned back to the user?
<?php
$zip = new ZipArchive;
$res = $zip->open('/download/xxxx.zip');
if ($res === TRUE) {
$zip->extractTo('/download/pdf/');
for($i = 0; $i < $zip->numFiles; $i++)
{
echo 'download';
}
$zip->close();
} else {
echo 'Something went wrong :( ';
}
?>
Thank you
Dexas solution worked for me. Here's the code if you need it
I've added in comments to show what I've changed.
<?php
$zip = new ZipArchive;
$res = $zip->open('/download/xxxxx.zip');
if ($res === TRUE) {
$zip->extractTo('/download/pdf/');
for($i = 0; $i < $zip->numFiles; $i++)
{
//Load files into variable which can be used with the following... ['dirname'], ['basename'], ['extension'], ['filename']
$path_parts = pathinfo('/download/pdf/' . $zip->getNameIndex($i));
//If the extension is equal to PDF echo the code out
if($path_parts['extension'] === 'pdf')
{
echo 'download';
}
}
$zip->close();
} else {
echo 'Something went wrong :( ';
}
?>
You can check it's MIME type using finfo
$finfo = new finfo(FILEINFO_MIME);
$type = $finfo->file('/path/to/file');
if($type === 'application/pdf')
{
//do your stuff
}
For the extension part you can use pathinfo
$ext = pathinfo('/path/to/file', PATHINFO_EXTENSION);
In the end you should check both and decide is it PDF or not.
$zip = new ZipArchive();
$filename = "image/files.zip";
if ($zip->open($filename, ZipArchive::CREATE)!==TRUE) {
exit("cannot open <$filename>\n");
}
$zip->addFile("$File", basename($File));
$zip->close();
I have added one file already in the zip, which is in variable '$File'. That file exists in the same folder (images). I need to add images in the same zip file. Those images are located inside 'images' folder. I guess I need to scan the images and add them into to same zip. But I'm not sure how to do that.
How can I get specific type(jpeg, png, gif) of files added into an existing zip file or a new one? I have to add images in the root of my zip file, not inside any folder within the zip file. The images are inside one directory('images') and I need to add those into my zip file, which is also saved inside the same directory.
$zip = new ZipArchive;
if ($zip->open('source.zip') === TRUE)
{
for($i = 0; $i < $zip->numFiles; $i++)
{
$fp = $zip->getStream($zip->getNameIndex($i));
if(!$fp) exit("failed\n");
while (!feof($fp)) {
$contents = fread($fp, 8192);
// explode for extension and do what ever you want
}
fclose($fp);
}
}
else
{
echo 'Error reading zip-archive!';
}
This is how I solved it.
$dir = './property_image';
$file1 = scandir($dir);
foreach($file1 as $feel){
$userfile_extn = substr($feel, strrpos($feel, '.')+1);
if($userfile_extn === 'jpg' || $userfile_extn === 'png' || $userfile_extn === 'gif' || $userfile_extn === 'jpeg'){
if(in_array($feel, $prop_image)){
//echo $feel;
$zip->addFile("./property_image/$feel", basename($feel));
}
} // end of if($extension ===
} // end of foreach
I'm in need of unziping uploaded content. But for security purposes must verify the files are only image files so that somebody can't add a php into the zip and then run it later.
While doing the unzip I need to preseverve the file structure as well.
$zip->extractTo($save_path . $file_name, array('*.jpg','*.jpeg','*.png','*.gif') );
doesn't return null. Is there a parameter I can use for this or must I iterate with a loop through the zip file using regex to match extensions and create the folders and save the files with code??
Thanks
from php.net, handling .txt files
<?php
$value="test.zip";
$filename="zip_files/$value";
$zip = new ZipArchive;
if ($zip->open($filename) === true) {
echo "Generating TEXT file.";
for($i = 0; $i < $zip->numFiles; $i++) {
$entry = $zip->getNameIndex($i);
if(preg_match('#\.(txt)$#i', $entry))
{
////This copy function will move the entry to the root of "txt_files" without creating any sub-folders unlike "ZIP->EXTRACTO" function.
copy('zip://'.dirname(__FILE__).'/zip_files/'.$value.'#'.$entry, 'txt_files/'.$value.'.txt');
}
}
$zip->close();
}
else{
echo "ZIP archive failed";
}
?>
for anyone who would need this in the future here is my solution. Thanks Ciro for the post, I only had to extend yours a bit. To make sure all folders are created I loop first for the folders and then do the extarction.
$ZipFileName = dirname(__FILE__)."/test.zip";
$home_folder = dirname(__FILE__)."/unziped";
mkdir($home_folder);
$zip = new ZipArchive;
if ($zip->open($ZipFileName ) === true)
{
//make all the folders
for($i = 0; $i < $zip->numFiles; $i++)
{
$OnlyFileName = $zip->getNameIndex($i);
$FullFileName = $zip->statIndex($i);
if ($FullFileName['name'][strlen($FullFileName['name'])-1] =="/")
{
#mkdir($home_folder."/".$FullFileName['name'],0700,true);
}
}
//unzip into the folders
for($i = 0; $i < $zip->numFiles; $i++)
{
$OnlyFileName = $zip->getNameIndex($i);
$FullFileName = $zip->statIndex($i);
if (!($FullFileName['name'][strlen($FullFileName['name'])-1] =="/"))
{
if (preg_match('#\.(jpg|jpeg|gif|png)$#i', $OnlyFileName))
{
copy('zip://'. $ZipFileName .'#'. $OnlyFileName , $home_folder."/".$FullFileName['name'] );
}
}
}
$zip->close();
} else
{
echo "Error: Can't open zip file";
}
I have a zip file uploaded to server for automated extract.
the zip file construction is like this:
/zip_file.zip/folder1/image1.jpg
/zip_file.zip/folder1/image2.jpg
/zip_file.zip/folder1/image3.jpg
Currently I have this function to extract all files that have extension of jpg:
$zip = new ZipArchive();
if( $zip->open($file_path) ){
$files = array();
for( $i = 0; $i < $zip->numFiles; $i++){
$entry = $zip->statIndex($i);
// is it an image?
if( $entry['size'] > 0 && preg_match('#\.(jpg)$#i', $entry['name'] ) ){
$f_extract = $zip->getNameIndex($i);
$files[] = $f_extract;
}
}
if ($zip->extractTo($dir_name, $files) === TRUE) {
} else {
return FALSE;
}
$zip->close();
}
But by using the function extractTo, it will extract to myFolder as ff:
/myFolder/folder1/image1.jpg
/myFolder/folder1/image2.jpg
/myFolder/folder1/image3.jpg
Is there any way to extract the files in folder1 to the root of myFolder?
Ideal:
/myFolder/image1.jpg
/myFolder/image2.jpg
/myFolder/image3.jpg
PS: incase of conflict file name I only need to not extract or overwrite the file.
Use this little code snippet instead. It removes the folder structure in front of the filename for each file so that the whole content of the archive is basically extracted to one folder.
<?php
$path = "zip_file.zip";
$zip = new ZipArchive();
if ($zip->open($path) === true) {
for($i = 0; $i < $zip->numFiles; $i++) {
$filename = $zip->getNameIndex($i);
$fileinfo = pathinfo($filename);
copy("zip://".$path."#".$filename, "/myDestFolder/".$fileinfo['basename']);
}
$zip->close();
}
?>
Here: (i tried to manage everything)
$zip = new ZipArchive();
if( $zip->open($file_path) ){
$files = array();
for( $i = 0; $i < $zip->numFiles; $i++){
$entry = $zip->statIndex($i);
// is it an image?
if( $entry['size'] > 0 && preg_match('#\.(jpg)$#i', $entry['name'] ) ){
$f_extract = $zip->getNameIndex($i);
$files[] = $f_extract; /* you man want to keep this array (use it to show result or something else) */
if ($zip->extractTo($dir_name, $f_extract) === TRUE) {
$solid_name = basename($f_extract);
if(strpos($f_extract, "/")) // make sure zipped file is in a directory
{
if($dir_name{strlen($dir_name)-1} == "/") $dir_name = substr($dir_name, 0, strlen($dir_name)-1); // to prevent error if $dir_name have slash in end of it
if(!file_exists($dir_name."/".$solid_name)) // you said you don't want to replace existed file
copy($dir_name."/".$f_extract, $dir_name."/".$solid_name); // taking file back to where you need [$dir_name]
unlink($dir_name."/".$f_extract); // [removing old file]
rmdir(str_replace($solid_name, "", $dir_name."/".$f_extract)); // [removing directory of it]
}
} else {
echo("error on export<br />\n");
}
}
}
$zip->close();
}
You can do so by using the zip:// syntax instead of Zip::extractTo as described in the php manual on extractTo().
You have to match the image file name and then copy it:
if ($entry['size'] > 0 && preg_match('#\.(jpg)$#i', $entry['name'])) {
copy('zip://' . $file_path . '#' . $entry['name'], '/root_dir/' . md5($entry['name']) . '.jpg');
}
The above replaces your for loop's if statement and makes your extractTo unnecessary. I used the md5 hash of the original filename to make a unique name. It is extremely unlikely you will have any issues with overwriting files, since hash collisions are rare. Note that this is a bit heavy duty, and instead you could do str_replace('/.', '', $entry['name']) to make a new, unique filename.
Full solution (modified version of your code):
<?php
$zip = new ZipArchive();
if ($zip->open($file_path)) {
for ($i = 0; $i < $zip->numFiles; $i++) {
$entry = $zip->statIndex($i);
// is it an image?
if ($entry['size'] > 0 && preg_match('#\.(jpg)$#i', $entry['name'])) {
# use hash (more expensive, but can be useful depending on what you're doing
$new_filename = md5($entry['name']) . '.jpg';
# or str_replace for cheaper, potentially longer name:
# $new_filename = str_replace('/.', '', $entry['name']);
copy('zip://' . $file_path . '#' . $entry['name'], '/myFolder/' . $new_filename);
}
}
$zip->close();
}
?>