I'm searching for a good solution to read a zip file from an url with php.
I checked the zip_open() function, but i never read anything about reading the file from another server.
Thank you very much
The best way to do that is to copy the remote file in a temporary one:
$file = 'http://remote/url/file.zip';
$newfile = 'tmp_file.zip';
if (!copy($file, $newfile)) {
echo "failed to copy $file...\n";
}
Then, you can do whatever you want with the temporary file:
$zip = new ZipArchive();
if ($zip->open($newFile, ZIPARCHIVE::CREATE)!==TRUE) {
exit("cannot open <$filename>\n");
}
This is a basic example:
$url = 'https://my.domain.com/some_zip.zip?blah=1&hah=2';
$destination_dir = '/path/to/local/storage/directory/';
if (!is_dir($destination_dir)) {
mkdir($destination_dir, 0755, true);
}
$local_zip_file = basename(parse_url($url, PHP_URL_PATH)); // Will return only 'some_zip.zip'
if (!copy($url, $destination_dir . $local_zip_file)) {
die('Failed to copy Zip from ' . $url . ' to ' . ($destination_dir . $local_zip_file));
}
$zip = new ZipArchive();
if ($zip->open($destination_dir . $local_zip_file)) {
for ($i = 0; $i < $zip->numFiles; $i++) {
if ($zip->extractTo($destination_dir, array($zip->getNameIndex($i)))) {
echo 'File extracted to ' . $destination_dir . $zip->getNameIndex($i);
}
}
$zip->close();
// Clear zip from local storage:
unlink($destination_dir . $local_zip_file);
}
Download the file contents (possibly with file_get_contents, or copy to put it on your filesystem) then apply the unzip algorithm.
Related
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();
}
}
I have this piece of code..,everything works fine ,but an issue with renaming
$zip = new ZipArchive();
$zipPath = 'images/userfiles/'.$company_details->company_name.'_products.zip';
$emptydir = $company_details->company_name.'_product_logos';
if ($zip->open($zipPath, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE)) {
$new_filename = substr($my_file, strrpos($my_file, '/') + 1);
$zip->addFile($my_file, $new_filename);
$zip->addEmptyDir($emptydir);
foreach($parts_list as $pl) {
if(!empty($pl['part_image'])){
if (file_exists($_SERVER['DOCUMENT_ROOT'] . $baseurl . '/images/group-logo/' . $pl['part_image'])) {
$img_file = 'images/group-logo/' . $pl['part_image'];
$new_filename2 = substr($img_file, strrpos($img_file, '/') + 1);
$zip->addFile($img_file,$emptydir . '/' . $new_filename2);
/*********the problem here******
Is there any way to rename the file that i added on the previous line to something else ,already tried zip rename and renameindex but not working
for example i want to rename the file $new_filename2 to $new_filename2.'something' with out affecting the original file's name
P.S the files to be renamed are inside another folder in the zip
*******************************/
}
}
}
$zip->close();
}
Since you do not want to effect the original file I would think that you are going to need to include a copy statement. Something like;
$file = '$new_filename2';
$newfile = '$new_filename2.zip';
if (!copy($file, $newfile)) {
echo "failed to copy $file...\n";
Okay i figured it out
Zip creates a lock on the file..you cant rename on the fly ,close it and rename again
$zip->addFile('.....');
....
$zip->close();
and open zip again and rename
I made a drupal module, one of function of the module is to compress some files to be a zip package. It works fine in my local environment(xampp), but fails on server. My server does has php zip extension enabled, since I can see zip information on php info and I can unzip file with php as well.
Besides, I already chmod files to be 0777 .
My code:
$folder = file_directory_path();
$zip = new ZipArchive();
if ($zip->open('b.zip', ZIPARCHIVE::CREATE) === TRUE) {
foreach ( $files as $file ) {
drupal_set_message(t($file)); // I can see the the message on this stpe
$zip->addFile($file);
}
$zip->close();
if (file_exists('b.zip')) {
copy('b.zip', $folder . '/b.zip');
unlink('b.zip');
global $base_url;
variable_set('zippath', $base_url . $folder . '/b.zip');
drupal_set_message(t('new zip package has been created'));
}
} else {
drupal_set_message(t('new zip package failed'));
}
Yes .. i know what you mean .. this are the 3 possibility
You have write permissions
You Did not use full path
You are including folders as file
You can try this
error_reporting(E_ALL);
ini_set("display_errors", "On");
$fullPath = __DIR__ ; // <-------- Full Path to directory
$fileZip = __DIR__ . "/b.zip"; // <--- Full path to zip
if(!is_writable($fullPath))
{
trigger_error("You can't Write here");
}
$files = scandir($fullPath); // <--- Just to emulate your files
touch($fileZip); // <----------------- Try Creating the file temopary
$zip = new ZipArchive();
if ($zip->open($fileZip, ZIPARCHIVE::CREATE) === TRUE) {
foreach ( $files as $file ) {
if ($file == "." || $file == "..")
continue;
$fileFull = $fullPath . "/$file";
if (is_file($fileFull)) { // <-------------- Make Sure its a file
$zip->addFile($fileFull, $file);
}
// Play your ball
}
$zip->close();
} else {
echo "Failed";
}
I would recommend you to use rar or zip command to make zip. I am using linux and doing in my php system as
$folder = 'your_folder'; // folder contains files to be archived
$zipFileName = 'Your_file_name'; // zip file name
$command = 'rar a -r ' . $zipFileName . ' ' . $folder . '/';
exec($command);
Its very quick. but you need to install rar package in your system.
Thanks
$file_name = 'New Folder.zip'
$zip = new ZipArchive;
$result = $zip->open($target_path.$file_name);
if ($result === TRUE) {
for($i = 0; $i < $zip->numFiles; $i++) {
$filename = $zip->getNameIndex($i);
$fileinfo = pathinfo($filename);
copy("zip://".$file_name."#".$filename, $target_path.$fileinfo['basename']);
}
}
When i run this code i get this error Warning: copy(zip://New Folder.zip#New Folder/icon_android.png) [function.copy]: failed to open stream: operation failed in...
How can I solve this...
From PHP's doc
$zip = new ZipArchive;
if ($zip->open('test.zip') === TRUE) {
$zip->extractTo($your_desired_dir);
$zip->close();
foreach (glob($your_desired_dir . DIRECTORY_SEPARATOR . 'New Folder') as $file) {
$finfo = pathinfo($file);
rename($file, $your_desired_dir . DIRECTORY_SEPARATOR . $finfo['basename']);
}
unlink($your_desired_dir . DIRECTORY_SEPARATOR . 'New Folder');
echo 'ok';
} else {
echo 'failed';
}
Dunno why are you using stream.
copy("zip://".$file_name."#".$filename, $target_path.$fileinfo['basename']);}
correct to
copy("zip://".dirname(__FILE__).'/'.$file_name."#".$filename, $target_path.$fileinfo['basename']);}
Full path need to use zip:// stream
see manual http://php.net/manual/en/book.zip.php
unzip.php (sample code)
// the first argument is the zip file
$in_file = $_SERVER['argv'][1];
// any other arguments are specific files in the archive to unzip
if ($_SERVER['argc'] > 2) {
$all_files = 0;
for ($i = 2; $i < $_SERVER['argc']; $i++) {
$out_files[$_SERVER['argv'][$i]] = true;
}
} else {
// if no other files are specified, unzip all files
$all_files = true;
}
$z = zip_open($in_file) or die("can't open $in_file: $php_errormsg");
while ($entry = zip_read($z)) {
$entry_name = zip_entry_name($entry);
// check if all files should be unzipped, or the name of
// this file is on the list of specific files to unzip
if ($all_files || $out_files[$entry_name]) {
// only proceed if the file is not 0 bytes long
if (zip_entry_filesize($entry)) {
$dir = dirname($entry_name);
// make all necessary directories in the file's path
if (! is_dir($dir)) { pc_mkdir_parents($dir); }
$file = basename($entry_name);
if (zip_entry_open($z,$entry)) {
if ($fh = fopen($dir.'/'.$file,'w')) {
// write the entire file
fwrite($fh,
zip_entry_read($entry,zip_entry_filesize($entry)))
or error_log("can't write: $php_errormsg");
fclose($fh) or error_log("can't close: $php_errormsg");
} else {
error_log("can't open $dir/$file: $php_errormsg");
}
zip_entry_close($entry);
} else {
error_log("can't open entry $entry_name: $php_errormsg");
}
}
}
}
from http://www.java-samples.com/showtutorial.php?tutorialid=985
First thing I would do is this:
echo "FROM - zip://".$file_name."#".$filename;
echo "<BR>TO - " . $target_path.$fileinfo['basename'];
and see what you get
I have used very simple method to do this
system('unzip assets_04_02_2015.zip');
I have a zip file.
I need a simple way to read the name of the files from the zip and read the contents of one of the files.
Can this be done directly in memory without saving,opening and reading the files ?
You need to open the archive and then can iterate over the files by index:
$zip = new ZipArchive();
if ($zip->open('archive.zip'))
{
for($i = 0; $i < $zip->numFiles; $i++)
{
echo 'Filename: ' . $zip->getNameIndex($i) . '<br />';
}
}
else
{
echo 'Error reading .zip!';
}
To read the content of a single file you can use ZipArchive::getStream($name).
$zip = new ZipArchive();
$zip->open("archive.zip");
$fstream = $zip->getStream("index.txt");
if(!$fp) exit("failed\n");
while (!feof($fp)) {
$contents .= fread($fp, 2);
}
Another way to directly do it is using the zip:// stream wrapper:
$file = fopen('zip://' . dirname(__FILE__) . '/test.zip#test', 'r');
...