How to rename and save Unzip file in php - php

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');
}

Related

Php zip files without directory tree

I am creating script zipping files from an array.
/* creates a compressed zip file */
function create_zip($files = array(),$destination = '',$overwrite = false) {
//if the zip file already exists and overwrite is false, return false
if(file_exists($destination) && !$overwrite) { return false; }
//vars
$valid_files = array();
//if files were passed in...
if(is_array($files)) {
//cycle through each file
foreach($files as $file) {
//make sure the file exists
if(file_exists($file)) {
$valid_files[] = $file;
}
}
}
//if we have good files...
if(count($valid_files)) {
//create the archive
$zip = new ZipArchive();
if($zip->open($destination,$overwrite ? ZIPARCHIVE::OVERWRITE : ZIPARCHIVE::CREATE) !== true) {
return false;
}
//add the files
foreach($valid_files as $file) {
$zip->addFile($file,$file);
}
//debug
//echo 'The zip archive contains ',$zip->numFiles,' files with a status of ',$zip->status;
//close the zip -- done!
$zip->close();
//check to make sure the file exists
return file_exists($destination);
}
else
{
return false;
}
}
#Mysql connect
$files_to_zip = array();
while($row = mysql_fetch_assoc($shots)) {
$files_to_zip[] = '/home/username/domains/example.com/public_html/components/items/images/item/' . $row["name"] . '_thb.' . $row["ext"];
}
if(isset($_POST['create'])){
//if true, good; if false, zip creation failed
$result = create_zip($files_to_zip,'my-archive5.zip');
}
After form submitting zip is created, but there's full directory tree inside files.
How to only zip files without directories?
Second thing:
When I open zip in total commander - I can see directories and files. When I open it normally - zip is empty.
The second argument to the addFile() method is the name of the file inside the zip. You're doing this:
$zip->addFile($file, $file);
So you're getting something like:
$zip->addFile('/path/to/some/file', '/path/to/some/file');
Which just copies the path from the source into the zip. If you want all the files to be in one dir in the zip, remove the path from the file name:
$zip->addFile($file, basename($file));
This will give you:
$zip->addFile('/path/to/some/file', 'file');
Note this won't work too well if you have files with the same name in different directories.
Check the docs on addFile method of Zip extension. You can specify local name as second argument.
Example from the documentation
<?php
$zip = new ZipArchive;
if ($zip->open('test.zip') === TRUE) {
$zip->addFile('/path/to/index.txt', 'newname.txt');
$zip->close();
echo 'ok';
} else {
echo 'failed';
}
?>

Can't create a zip archive with utf8-named cyrillic file

I try to create zip-archive with file фыфыфы.cs next way:
$zip = new ZipArchive;
if ($zip->open($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . '111.zip', ZIPARCHIVE::CREATE) === TRUE) {
$zip->addFile($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . 'фыфыфы.cs');
$zip->close();
echo 'ok';
} else {
echo 'error';
}
But the archive wasn't created. I tried to view the number of files in the archive after addFile call with:
die($zip->numFiles);
But I got 0.
When I renamed file to zzz.cs, the archive was created successfully. What's wrong?
I use Windows 8 at my PC.
I tried this solution, but it didn't work for me. A got the empty $encoded_filename.
for fix this I had to encode the $filename yet again to a different encoding, CP858.
Example:
$filename = "фыфыфы.cs";
//encode to windows-1252 to save to the filesystem
$encoded_filename = iconv("UTF-8","Windows-1252//IGNORE",$filename);
file_put_contents($encoded_filename, "text");
//put in a zip file
$zip = new ZipArchive();
$zip->open('test.zip', ZIPARCHIVE::CREATE);
//encode as CP858 to save into zip file
$zip->addFile($encoded_filename, iconv("UTF-8", "CP858//IGNORE", $filename));
$zip->close();
You can implement this method for your code.

PHP ZipArchive is not adding any files (Windows)

I'm failing to put even a single file into a new zip archive.
makeZipTest.php:
<?php
$destination = __DIR__.'/makeZipTest.zip';
$fileToZip = __DIR__.'/hello.txt';
$zip = new ZipArchive();
if (true !== $zip->open($destination, ZIPARCHIVE::OVERWRITE)) {
die("Problem opening zip $destination");
}
if (!$zip->addFile($fileToZip)) {
die("Could not add file $fileToZip");
}
echo "numfiles: " . $zip->numFiles . "\n";
echo "status: " . $zip->status . "\n";
$zip->close();
The zip gets created, but is empty. Yet no errors are triggered.
What is going wrong?
It seems on some configuration, PHP fails to get the localname properly when adding files to a zip archive and this information must be supplied manually. It is therefore possible that using the second parameter of addFile() might solve this issue.
ZipArchive::addFile
Parameters
filename
The path to the file to add.
localname
If supplied, this is the local name inside the ZIP archive that will override the filename.
PHP documentation: ZipArchive::addFile
$zip->addFile(
$fileToZip,
basename($fileToZip)
);
You may have to adapt the code to get the right tree structure since basename() will remove everything from the path apart from the filename.
You need to give server right permission in folder where they create zip archive. You can create tmp folder with write permision chmod 777 -R tmp/
Also need to change destination where script try to find hello.txt file $zip->addFile($fileToZip, basename($fileToZip))
<?php
$destination = __DIR__.'/tmp/makeZipTest.zip';
$fileToZip = __DIR__.'/hello.txt';
$zip = new ZipArchive();
if (true !== $zip->open($destination, ZipArchive::OVERWRITE)) {
die("Problem opening zip $destination");
}
if (!$zip->addFile($fileToZip, basename($fileToZip))) {
die("Could not add file $fileToZip");
}
echo "numfiles: " . $zip->numFiles . "\n";
echo "status: " . $zip->status . "\n";
$zip->close()
check this class to add files and sub-directories in a folder to zip file,and also check the folder permissions before running the code,
i.e chmod 777 -R zipdir/
HZip::zipDir('/path/to/sourceDir', '/path/to/out.zip');
<?php
class HZip
{
private static function folderToZip($folder, &$zipFile, $exclusiveLength) {
$handle = opendir($folder);
while (false !== $f = readdir($handle)) {
if ($f != '.' && $f != '..') {
$filePath = "$folder/$f";
// Remove prefix from file path before add to zip.
$localPath = substr($filePath, $exclusiveLength);
if (is_file($filePath)) {
$zipFile->addFile($filePath, $localPath);
} elseif (is_dir($filePath)) {
// Add sub-directory.
$zipFile->addEmptyDir($localPath);
self::folderToZip($filePath, $zipFile, $exclusiveLength);
}
}
}
closedir($handle);
}
public static function zipDir($sourcePath, $outZipPath)
{
$pathInfo = pathInfo($sourcePath);
$parentPath = $pathInfo['dirname'];
$dirName = $pathInfo['basename'];
$z = new ZipArchive();
$z->open($outZipPath, ZIPARCHIVE::CREATE);
$z->addEmptyDir($dirName);
self::folderToZip($sourcePath, $z, strlen("$parentPath/"));
$z->close();
}
}

Extracting zip file on host by PHP destroys directory structure

I have a directory structure like this :
members/
login.php
register.php
I zip them by PHP ZipArchive in my windows machine, but when I upload it to linux host and extract there by PHP it gives me these as two files with no directory :
members\login.php
members\register.php
I want to have the complete directory structure on the host after unzipping the file.
Note that this unpacking code runs without any problem in my local machine. Is it something about windows and linux or what? How can I resolve it?
PHP does not actually provide a function that extracts a ZIP including its directory structure. I found the following code in a user comment in the manual:
function unzip($zipfile)
{
$zip = zip_open($zipfile);
while ($zip_entry = zip_read($zip)) {
zip_entry_open($zip, $zip_entry);
if (substr(zip_entry_name($zip_entry), -1) == '/') {
$zdir = substr(zip_entry_name($zip_entry), 0, -1);
if (file_exists($zdir)) {
trigger_error('Directory "<b>' . $zdir . '</b>" exists', E_USER_ERROR);
return false;
}
mkdir($zdir);
}
else {
$name = zip_entry_name($zip_entry);
if (file_exists($name)) {
trigger_error('File "<b>' . $name . '</b>" exists', E_USER_ERROR);
return false;
}
$fopen = fopen($name, "w");
fwrite($fopen, zip_entry_read($zip_entry, zip_entry_filesize($zip_entry)), zip_entry_filesize($zip_entry));
}
zip_entry_close($zip_entry);
}
zip_close($zip);
return true;
}
Source here.
try DIRECTORY_SEPARATOR
instead of using:
$path = $someDirectory.'/'.$someFile;
use:
$path = $someDirectory. DIRECTORY_SEPARATOR .$someFile;
Change your code to this:
$zip = new ZipArchive;
if ($zip->open("module. DIRECTORY_SEPARATOR .$file[name]") === TRUE) {
$zip->extractTo('module. DIRECTORY_SEPARATOR');
}
And it will work for both operating systems.
Good luck,
The problem solved! Here's what I did :
I change the code of creating zip file into this function from php.net user comments :
function addFolderToZip($dir, $zipArchive){
if (is_dir($dir)) {
if ($dh = opendir($dir)) {
//Add the directory
$zipArchive->addEmptyDir($dir);
// Loop through all the files
while (($file = readdir($dh)) !== false) {
//If it's a folder, run the function again!
if(!is_file($dir . $file)){
// Skip parent and root directories
if(($file !== ".") && ($file !== "..")){
addFolderToZip($dir . $file . "/", $zipArchive);
}
}else{
// Add the files
$zipArchive->addFile($dir . $file);
}
}
}
}
}
$zip = new ZipArchive;
$zip->open("$modName.zip", ZipArchive::CREATE);
addFolderToZip("$modName/", $zip);
$zip->close();
And in the host I wrote just this code to extract the zipped file :
copy($file["tmp_name"], "module/$file[name]");
$zip = new ZipArchive;
if ($zip->open("module/$file[name]") === TRUE) {
$zip->extractTo('module/');
}
$zip->close();
It created the folder and sub-folders. The only bug left is that it extracts every file in all subfolders in the main folder too, so there is two versions of each file in subfolders.

php creating zips without path to files inside the zip

I'm trying to use php to create a zip file (which it does - taken from this page - http://davidwalsh.name/create-zip-php), however inside the zip file are all of the folder names to the file itself.
Is it possible to just have the file inside the zip minus all the folders?
Here's my code:
function create_zip($files = array(), $destination = '', $overwrite = true) {
if(file_exists($destination) && !$overwrite) { return false; };
$valid_files = array();
if(is_array($files)) {
foreach($files as $file) {
if(file_exists($file)) {
$valid_files[] = $file;
};
};
};
if(count($valid_files)) {
$zip = new ZipArchive();
if($zip->open($destination,$overwrite ? ZIPARCHIVE::OVERWRITE : ZIPARCHIVE::CREATE) !== true) {
return false;
};
foreach($valid_files as $file) {
$zip->addFile($file,$file);
};
$zip->close();
return file_exists($destination);
} else {
return false;
};
};
$files_to_zip = array('/media/138/file_01.jpg','/media/138/file_01.jpg','/media/138/file_01.jpg');
$result = create_zip($files_to_zip,'/...full_site_path.../downloads/138/138_files.zip');
The problem here is that $zip->addFile is being passed the same two parameters.
According to the documentation:
bool ZipArchive::addFile ( string $filename [, string $localname ] )
filename
The path to the file to add.
localname
local name inside ZIP archive.
This means that the first parameter is the path to the actual file in the filesystem and the second is the path & filename that the file will have in the archive.
When you supply the second parameter, you'll want to strip the path from it when adding it to the zip archive. For example, on Unix-based systems this would look like:
$new_filename = substr($file,strrpos($file,'/') + 1);
$zip->addFile($file,$new_filename);
I think a better option would be:
$zip->addFile($file,basename($file));
Which simply extracts the filename from the path.
This is just another method that I found that worked for me
$zipname = 'file.zip';
$zip = new ZipArchive();
$tmp_file = tempnam('.','');
$zip->open($tmp_file, ZipArchive::CREATE);
$download_file = file_get_contents($file);
$zip->addFromString(basename($file),$download_file);
$zip->close();
header('Content-disposition: attachment; filename='.$zipname);
header('Content-type: application/zip');
readfile($tmp_file);
I use this to remove root folder from zip
D:\xampp\htdocs\myapp\assets\index.php
wil be in zip:
assets\index.php
our code:
echo $main_path = str_replace("\\", "/", __DIR__ );// get current folder, which call scipt
$zip_file = 'myapp.zip';
if (file_exists($main_path) && is_dir($main_path))
{
$zip = new ZipArchive();
if (file_exists($zip_file)) {
unlink($zip_file); // truncate ZIP
}
if ($zip->open($zip_file, ZIPARCHIVE::CREATE)!==TRUE) {
die("cannot open <$zip_file>\n");
}
$files = 0;
$paths = array($main_path);
while (list(, $path) = each($paths))
{
foreach (glob($path.'/*') as $p)
{
if (is_dir($p)) {
$paths[] = $p;
} else {
// special here: we remove root folder ("D:\xampp\htdocs\myapp\") :D
$new_filename = str_replace($main_path."/" , "", $p);
$zip->addFile($p, $new_filename);
$files++;
echo $p."<br>\n";
}
}
}
echo 'Total files: '.$files;
$zip->close();
}

Categories