PHP: how to retrieve the filename of the file contained in .gz? - php

My test.gz contains for instance : image1.jpg.
How can I decompress the test.gz so it gives me image1.jpg ?
I tried that method:
$file = gzopen($file_name, 'rb');
$out_file = fopen($out_file_name, 'wb');
but it supposes you need to know the filename contained in the .gz file
regards

You need to use PHP PharData to extract and read its content.
To extract tar or tar.gz :
$phar = new PharData('myphar.tar');
$phar->extractTo('/full/path');
And to list all files, you can use :
archive = new PharData('/upload/directory/myphar.tar.gz');
foreach (new RecursiveIteratorIterator($archive) as $file) {
echo $file . "<br />";
}

Related

cannot add xml file to zip laravel

I want to create a zip folder that includes an xml file and download it. I can download zip but it is empty.
I can create xml and zip :
By the way, $result is the result of ArrayToXml::convert(array,....)
$zip = new ZipArchive;
$fileName = 'example-'.time().'.xml';
$zipName = 'example'.time().'.zip';
if ($zip->open(public_path("storage/zips/".$zipName), ZipArchive::CREATE) === TRUE)
{
Storage::disk('public')->put('/files/'.$fileName, $result);
$zip->addFile(public_path("storage/files/".$fileName), $result);
Storage::disk('public')->put('/zips/'.$zipName, $zip);
$zip->close();
}
return response()->download(storage_path('app\public\zips\\'.$zipName));
How to add xml file to zip. I am new to laravel please help
Have a look at the Madzipper package. Makes working with zip files very easy.
You can create a zipfile as follows:
$fileName = 'example-'.time() . '.xml';
$zip = 'public/zips/example' . time() . '.zip';
Madzipper::make($zip)->addString($fileName, $result)->close();
And then return the path to $zip when downloading the file.
Please have a look at the docs for more info.

use PHP ZipArchive with file as variable

In a symfony Controller I have a file (UploadedFile object) as a variable.
I want to open this "variable" with php ZipArchive, and extract it.
But the open() methods is expecting a string, which is the filename in the filesystem. Is there any way to process the file with the ZipArchive and without writing the file variable to the FS?
You can use tmpfile() to create a temporary file, write to it and then use it in the zip. Example:
<?php
$zip = new ZipArchive();
$zip->open(__DIR__ . '/zipfile.zip', ZipArchive::CREATE);
$fp = tmpfile();
fwrite($fp, 'Test');
$filename = stream_get_meta_data($fp)['uri'];
$zip->addFile($filename, 'filename.txt');
$zip->close();
fclose($fp);
Little improve:
$zipContent; // in this variable could be ZIP, DOCX, XLSX etc.
$fp = tmpfile();
fwrite($fp, $zipContent);
$stream = stream_get_meta_data($fp);
$filename = $stream['uri'];
$zip = new ZipArchive();
$zip->open($filename);
// profit!
$zip->close();
fclose($fp);
Just make no sense to create "zipfile.zip" and add file inside, because we already have a variable.
Check out this answer at https://stackoverflow.com/a/53902626/859837
There is a way to create a file which resides in memory only.

How to check whether the upload file is PDF in PHP

For an upload file type checking , I have implemented:
$_FILES["file"]["type"][$i] == 'application/pdf'
however, this checking will not work on the case I changed the extension name.
So , after some research, I have tried
$finfo = new finfo();
$fileMimeType = $finfo->file($_FILES["file"]["name"][$i] );
OR:
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$fileMimeType = finfo_file($finfo,$_FILES["file"]["name"][$i])
however, $fileMimeType echo nothing.
How to fix the problem? thanks
Read the first 4 bytes of the file and check that they match %PDF.
$filename = "pdffile";
$handle = fopen($filename, "r");
$header = fread($handle, 4);
fclose($handle);
Check $header against %PDF
I guess the problem is using:
$_FILES["my_file"]["name"]
as it only contains the name of the uploaded file. If you want to check the file before moving it using move_uploaded_file you can refer to the temp file using:
$_FILES["my_file"]["tmp_name"]
if you read the file using fread you need to have a dictionary of all the file header type definitions. If you want to use the file shell command
$out = exec("file 'R-intro.pdf' | cut -d: -f2 | cut -d, -f1");
if (trim($out) == "PDF document") {
echo "1";
}
To further expand on how to replace the constant file name with a uploaded file refer below.
$out = exec("file '" . $_FILES['file']['tmp_name'] . "' | cut -d: -f2 | cut -d, -f1");

Read only pdf files and get the filename of that pdf files in a directory

I need to read only pdf files in a directory and then read the filename of every files then I will use the filename to rename some txt files. I have tried using only eregi function. but it seems cannot read all I need. how to read them well?
here's my code :
$savePath ='D:/dir/';
$dir = opendir($savePath);
$filename = array();
while ($filename = readdir($dir)) {
if (eregi("\.pdf",$filename)){
$read = strtok ($filename,"."); //get the filenames
//to rename some txt files using the filenames that I get before
//$testfile is text files that I've read before
$testfile = "$read.txt";
$file = fopen($testfile,"r") or die ('cannot open file');
if (filesize($testfile)==0){}
else{
$text = fread($file,55024);
fclose($file);
echo "</br>"; echo "</br>";
}
}
More elegant:
foreach (glob("D:/dir/*.pdf") as $filename) {
// do something with $filename
}
To get the filename only:
foreach (glob("D:/dir/*.pdf") as $filename) {
$filename = basename($filename);
// do something with $filename
}
You can do this by filter file type.. following is sample code.
<?php
// directory path can be either absolute or relative
$dirPath = '.';
// open the specified directory and check if it's opened successfully
if ($handle = opendir($dirPath)) {
// keep reading the directory entries 'til the end
$i=0;
while (false !== ($file = readdir($handle))) {
$i++;
// just skip the reference to current and parent directory
if (eregi("\.jpg",$file) || eregi("\.gif",$file) || eregi("\.png",$file)){
if (is_dir("$dirPath/$file")) {
// found a directory, do something with it?
echo " [$file]<br>";
} else {
// found an ordinary file
echo $i."- $file<br>";
}
}
}
// ALWAYS remember to close what you opened
closedir($handle);
}
?>
Above is demonstrating for file type related to images you can do the same for .PDF files.
Better explained here

In memory download and extract zip archive

I would like to download a zip archive and unzip it in memory using PHP.
This is what I have today (and it's just too much file-handling for me :) ):
// download the data file from the real page
copy("http://www.curriculummagic.com/AdvancedBalloons.kmz", "./data/zip.kmz");
// unzip it
$zip = new ZipArchive;
$res = $zip->open('./data/zip.kmz');
if ($res === TRUE) {
$zip->extractTo('./data');
$zip->close();
}
// use the unzipped files...
Warning: This cannot be done in memory — ZipArchive cannot work with "memory mapped files".
You can obtain the data of a file inside a zip-file into a variable (memory) with file_get_contentsDocs as it supports the zip:// Stream wrapper Docs:
$zipFile = './data/zip.kmz'; # path of zip-file
$fileInZip = 'test.txt'; # name the file to obtain
# read the file's data:
$path = sprintf('zip://%s#%s', $zipFile, $fileInZip);
$fileData = file_get_contents($path);
You can only access local files with zip:// or via ZipArchive. For that you can first copy the contents to a temporary file and work with it:
$zip = 'http://www.curriculummagic.com/AdvancedBalloons.kmz';
$file = 'doc.kml';
$ext = pathinfo($zip, PATHINFO_EXTENSION);
$temp = tempnam(sys_get_temp_dir(), $ext);
copy($zip, $temp);
$data = file_get_contents("zip://$temp#$file");
unlink($temp);
As easy as:
$zipFile = "test.zip";
$fileInsideZip = "somefile.txt";
$content = file_get_contents("zip://$zipFile#$fileInsideZip");
Old subject but still relevant since I asked myself the same question, without finding an answer.
I ended up writing this function which returns an array containing the name of each file contained in the archive, as well as the decompressed contents of that file:
function GetZipContent(String $body_containing_zip_file) {
$sectors = explode("\x50\x4b\x01\x02", $data);
array_pop($sectors);
$files = explode("\x50\x4b\x03\x04", implode("\x50\x4b\x01\x02", $sectors));
array_shift($files);
$result = array();
foreach($files as $file) {
$header = unpack("vversion/vflag/vmethod/vmodification_time/vmodification_date/Vcrc/Vcompressed_size/Vuncompressed_size/vfilename_length/vextrafield_length", $file);
array_push($result, [
'filename' => substr($file, 26, $header['filename_length']),
'content' => gzinflate(substr($file, 26 + $header['filename_length'], -12))
]);
}
return $result;
}
Hope this is useful ...
You can get a stream to a file inside the zip and extract it into a variable:
$fp = $zip->getStream('test.txt');
if(!$fp) exit("failed\n");
while (!feof($fp)) {
$contents .= fread($fp, 1024);
}
fclose($fp);
If you can use system calls, the simplest way should look like this (bzip2 case). You just use stdout.
$out=shell_exec('bzip2 -dkc '.$zip);

Categories