Problems when extract ZIP file in PHP - php

I'm trying to extract zip file to some folder in storage_path (I'm using laravel). But I don't know why they comes with .(dot)files when it extracted, also I want to extract them without creating another folder. Here's the code I'm using:
lines inside some public function:
$src = storage_path('application');
$dst = storage_path('tmp/'.time());
$zipfile = $request->file('splashicon');
$zipfile->move($dst, 'splashicon');
$this->splashIcon($dst.'/splashicon', $dst);
splashIcon function:
public function splashIcon($src, $dst)
{
$zip = new ZipArchive();
$x = $zip->open($src); // open the zip file to extract
if ($x === true) {
$zip->extractTo($dst.'/www'); // place in the directory with same name
$zip->close();
unlink($src); //Deleting the Zipped file
}
}
The current result is:
1494618313/www/name.files/thecontentsofzipfile
I have no idea where .(dot) and files came from, please explain what was happened to them.
And by the way, the correct result should be something like this:
1494618313/www/thecontentsofzipfile
Thank you,

This is a laravel convention.
The . means it's a subfolder/subfile within your directory.
I'm not really sure how to get around it.
You might look into Zipper, which is an extraction helper for Laravel. I believe it has an exact match for extraction instead of using the typical Laravel syntax.
https://github.com/Chumper/Zipper

Related

PHP — Information on the zip:// protocol

I am using ZipArchive class to unzip a file and put its contents somewhere useful. Using information derived from the comments on php.net, I ended up writing this function:
function unzip(string $zipFile, string $destination) {
$zip = new ZipArchive();
$zip->open($zipFile);
for($i=0; $i<$zip->numFiles; $i++) {
$file=$zip->getNameIndex($i);
if(substr($file,-1) == '/') continue; // skip containing folder
$name=basename($file);
copy("zip://$zipFile#$file","$destination/$name");
}
$zip->close();
}
This is to copy the individual files without the folder structure.
I can understand most of the code, but I cannot get any information on the following expression:
"zip://$zipFile#$file"
I know what it doing (obviously it is extracting one of the files from the Zip archive), but can anyone tell me more about the zip:// protocol, and why it uses the # to reference a particular file?
Check out source of Zip extension
https://github.com/php/php-src/blob/master/ext/zip/zip_stream.c
line 135. fragment = strchr(path, '#');
get pointer of entry in path/to/zip#entry
line 141.
if (strncasecmp("zip://", path, 6) == 0)
{
path += 6;
}
if zip:// is equal first 6 characters of path
I won't go into the logic of this code. It just exists here (zip_stream.c) and maybe somewhere else.
It seems like this extension "creates" zip:// protocol over php executable that is laying over apache server.

Php keyword search in file name in a directory and download

I have a list of files in a directory of some local path with names like APX-904-118000945-NMR-ETC with different extensions. For every file name a code exists, in this filename 118000945, using which i want to search and download that file in php.
I am able to pass the code i.e., 118000945 but unable to search for it and download with some piece of code got from web.
Could you help me out in writing a php script for this?
Consider using the symfony finder component
$idToFind = '118000945';
$finder = new Finder();
$finder->files()
->in('/path/to/dir')
->name(sprintf('*%s*', $idToFind));
foreach ($finder as $file) {
$absoluteFilePath = $file->getRealPath();
$fileNameWithExtension = $file->getRelativePathname();
// ...
}

Unable to extract zip file which generated using php

I have written the PHP script to generate the zip file. it's working fine when I use rar software to extract it but not getting extract with rar software. I can't ask to users to install rar software to extract downloaded zip file.
I don't know where i am commiting mistakes.
Here i attached error screen shot which i get when try to open zip file.
// Here is code snippet
$obj->create_zip($files_to_zip, $dir . '/download.zip');
// Code for create_zip function
//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) {
$filearr = explode('/', $file);
$zip->addFile($file, end($filearr));
}
$zip->close();
If $valid_files is a glob'd array, use basename() instead of end(), your zip might not actually have added any files causing for it to be an invalid zip (however that would be visible in the size of the zip file).
Also try winrar/winzip/7zip and see what they return, microsoft's internal zip engine might not be up to date enough to open the zips.
I have also encountered this problem, using 7z solved the problem but we need to send the zip to somebody else so 7z is a nono.
I found that, in my case it is that the file path is too long:
When I use this:
$zip->addFile($files_path.'/people.txt');
And it generated a zip folder nested very deep e.g. ["/tmp/something/something1/something2/people.txt"]
So I need to use this instead
$zip->addFile($files_path.'/people.txt', 'people.txt');
Which generate a a zip folder with only 1 layer ["people.txt"], and Windows Zip read perfectly~
Hope this helps somebody that also have this problem!

PharData offsetExists on filename prefixed with ".\"

I have a .tar.gz file downloaded from an external API which we have to implement. It contains images for an object.
I'm not sure how they managed to compress it this way, but the files are basically prefixed with the "current directory". It looks like this in WinRAR:
And like this in 7-Zip, note the .tar first level, and "." second level:
-> ->
When calling
$file = 'archive.tar.gz';
$phar = new PharData($file, FilesystemIterator::CURRENT_AS_FILEINFO);
var_dump($phar->offsetGet('./12613_s_cfe3e73.jpg'));
I get the exception:
Cannot access phar file entry '/12613_s_cfe3e73.jpg' in archive '{...}/archive.tar.gz'
Calling a file which does not exist, e.g.:
var_dump($phar->offsetGet('non-existent.jpg'));
Or calling it without the directory seperator, e.g.:
var_dump($phar->offsetGet('12613_s_cfe3e73.jpg'));
I get a
Entry 12613_s_cfe3e73.jpg does not exist
Exception.
It is not possible to get the archive formatted differently. Does anyone have an idea how to solve this?
Ended up using Archive_Tar. There must be something wrong in the source code of PHP, though I don't think this is the "normal" way of packaging a .tar either.
Unfortunately I'm not very good at C, but it's probably in here (line 1214) or here.
This library seems to handle it just fine, using this example code:
$file = 'archive.tar.gz';
$zip = new Archive_Tar($file);
foreach ($zip->listContent() as $file) {
echo $file['filename'] . '<br>';
}
Result:
./12613_s_f3b483d.jpg
./12613_s_cfe3e73.jpg
./1265717_s_db141dc.jpg
./1265717_s_af5de56.jpg
./1265717_s_b783547.jpg
./1265717_s_35b11f9.jpg
./1265716_s_83ef572.jpg
./1265716_s_9ac2725.jpg
./1265716_s_c5af3e9.jpg
./1265716_s_c070da3.jpg
./1265715_s_4339e8a.jpg
Note the filenames are still prefixed with "./" just like they are in WinRAR.
If you want to stick to using PharData, i suggest a more conservative, two-step approach, where you first decompress the gz and then unarchive all files of the tar to a target folder.
// decompress gz archive to get "/path/to/my.tar" file
$gz = new PharData('/path/to/my.tar.gz');
$gz->decompress();
// unarchive all files from the tar to the target path
$tar = new PharData('/path/to/my.tar');
$tar->extractTo('/target/path');
But it looks like you want to select individual files from the tar.gz archive directly, right?
It should work using fopen() with a StreamReader (compress.zlib or phar) and selecting the individual file. Some examples:
$f = fopen("compress.zlib://http://some.website.org/my.gz/file/in/the/archive", "r");
$f = fopen('phar:///path/to/my.tar.gz//file/in/archive', 'r');
$filecontent = file_get_contents('phar:///some/my.tar.gz/some/file/in/the/archive');
Streaming should also work, when using Iterators:
$rdi = new RecursiveDirectoryIterator('phar:///path/to/my.tar.gz')
$rii = new RecursiveIteratorIterator($rdi, RecursiveIteratorIterator::CHILD_FIRST);
foreach ($rii as $splFileInfo){
echo file_get_contents($splFileInfo->getPathname());
}
The downside is that you have to buffer the stream and save it to file.
Its not a direct file extraction to a target folder.

Help with php function zip_open

It's now 5am, and as much as I try to research, I can't find much information on this function set. Here's the code I have (shortened slightly):
<?php
$source = $_FILES["restore_file"]["tmp_name"];
$zip = zip_open($source);
while ($zip_entry = zip_read($zip)) {
echo zip_entry_name($zip_entry).'\n';
}
?>
which when I upload my example zip out puts:
example/
example/index.php
example/file1.csv
example/file2.csv
example/file3.csv
etc.
I need to know how to access the contents of those files though, and also be able to specify which file I am accessing exactly. For example, before going through the csv files, I need to check a php variable in the index.php file of the archive, to make sure it is correct.
Is using the ZipArchive class a better idea instead of the zip functions perhaps? I was under the impression though that using the zip functions would be better as it can access the files on the fly (without having to transfer the files to a new directory).
Use ZipArchive::getFromName(). Example from the PHP manual adapted to your case:
$zip = new ZipArchive();
if ($zip->open($_FILES["restore_file"]["tmp_name"]) === true) {
echo $zip->getFromName('example/index.php');
$zip->close();
} else {
echo 'failed';
}

Categories