How do I add a list of files to an array and then add that array to a zip? I am using php in order to achieve this. I am able to add a single file without an array but adding an array is causing an issue.
<?
...
...
$file = array();
$file[] = "001.pdf";
$file[] = "002.pdf";
$length = count($file);
$zip = new ZipArchive;
$tmp_file = 'Documents.zip';
if($zip->open($tmp_file, ZipArchive::OVERWRITE|ZipArchive::CREATE)) {
for($i=0;$i < $length ;$i=$i+1) //Here is where i read the array
{
$zip->addFile($file, "$i.pdf"); //Here is the problem
}
$zip->close();
echo 'Archive created!';
header('Content-disposition: attachment; filename=Documents.zip');
header('Content-type: application/zip');
} else {
echo 'Failed!';
}
ob_end_clean();
readfile($tmp_file);
?>
Got it!
All i had to loop was foreach item instead of for loop.
foreach($file as $files) {
$zip->addFile($files,$files);
}
Related
I Have been reading many similar problems but I just can't find the solution to mine.
All I need is zip the files that come in the POST variable as an array and get the path to the zip file just created. Here is my code... I keep getting an empty Object and just can't make 1 file inside
function downloadAllImages(){
$data = array();
$files = $_POST['files_to_download'];
$archive_file_name = 'images.zip';
$zip = new ZipArchive();
//create the file and throw the error if unsuccessful
if ($zip->open($archive_file_name, ZIPARCHIVE::CREATE )!==TRUE) {
$data['debug'].=("cannot open <$archive_file_name>\n");
}
//add each files of $file_name array to archive
foreach($files as $file)
{
$zip->addFile($file, basename($file));
}
$zip->close();
//then send the headers to foce download the zip file
header("Content-type: application/zip");
header("Content-Disposition: attachment; filename=$archive_file_name");
header("Pragma: no-cache");
header("Expires: 0");
readfile("$archive_file_name");
$data['debug'].=print_r($zip,true);
echo json_encode($data);
die();
}
I'm using JQuery to get the download link after the file is zipped. I just can't make the files to zip.
The array files_to_download prints:
Array(
[0] => http://localhost/br/wp-content/uploads/2020/04/rabbit-black-transp-300x300.png
[1] => http://localhost/br/wp-content/uploads/2020/04/bg-shop-300x169.png
)
And my jQuery
function downloadAllImages(){
var files_to_download = [];
$("img.downloadable").each(function(){
files_to_download.push($(this).attr('src'));
});
jQuery.ajax({
url: runAJAX.ajaxurl,
data: ({action: 'downloadAllImages', files_to_download:files_to_download}),
method: "POST",
success: function(data_received) {
displayAjaxResponse(data_received);
}
});
}
In the end a friend of mine helped and the PHP code should look like this:
function downloadAllImages()
{
$data = array();
$files = $_POST['files_to_download']; // array
$domain= wp_upload_dir();
// used this to rename the file so each post gets it's own zip
$prefix=$_POST['file_prefix'];
$zip = new ZipArchive();
$tmp_zip = $zip->open($domain['basedir'].'/'.$prefix.'images.zip', ZipArchive::CREATE);
foreach($filesas $img)
{
if(!empty($img))
{
$download_file = file_get_contents($img);
$zip->addFromString(basename($img), $download_file);
}
}
$zip->close();
$now = new DateTime();
$data['file'] = get_bloginfo('wpurl')."/wp-content/uploads/{$prefix}images.zip?v={$now ->getTimestamp()}";
echo json_encode($data);
die();
}
And the jQuery looks pretty much the same, except for adding the 'file_prefix' variable.
This exports one file with 2 rows in it. How can export 2 files each with one row in it?
<?php
$list = array (
array("Peter", "Griffin" ,"Oslo", "Norway"),
array("Glenn", "Quagmire", "Oslo", "Norway")
);
$file = fopen("contacts.csv","w");
foreach ($list as $line) {
fputcsv($file, $line);
}
fclose($file);
?>
I tried this:
$list = array (
array("Peter", "Griffin" ,"Oslo", "Norway"),
array("Glenn", "Quagmire", "Oslo", "Norway")
);
$file = fopen('php://output', 'w');
$i = 1;
foreach ($list as $line) {
header('Content-Disposition: attachment; filename="' . $i . 'wp.csv"');
fputcsv($file, $line);
fclose($file);
$i++;
}
But it only downloads one file. At least it only has the one row in it though.
I found this example. Even though it creates 2 separate csv files, the data is identical in each file instead of each file containing an individual record.
// some data to be used in the csv files
$headers = array('id', 'name', 'age', 'species');
$records = array(
array('1', 'gise', '4', 'cat'),
array('2', 'hek2mgl', '36', 'human')
);
// create your zip file
$zipname = 'file.zip';
$zip = new ZipArchive;
$zip->open($zipname, ZipArchive::CREATE);
// loop to create 3 csv files
for ($i = 0; $i < 3; $i++) {
// create a temporary file
$fd = fopen('php://temp/maxmemory:1048576', 'w');
if (false === $fd) {
die('Failed to create temporary file');
}
// write the data to csv
fputcsv($fd, $headers);
foreach($records as $record) {
fputcsv($fd, $record);
}
// return to the start of the stream
rewind($fd);
// add the in-memory file to the archive, giving a name
$zip->addFromString('file-'.$i.'.csv', stream_get_contents($fd) );
//close the file
fclose($fd);
}
// close the archive
$zip->close();
header('Content-Type: application/zip');
header('Content-disposition: attachment; filename='.$zipname);
header('Content-Length: ' . filesize($zipname));
readfile($zipname);
// remove the zip archive
// you could also use the temp file method above for this.
unlink($zipname);
You can only put one "file" into an HTTP response.
If you want to generate multiple CSV files then you'll need to get more exotic. You could generate a HTML document of links to URLs that each generate a CSV file, or you could generate a zip file containing the CSV files.
Just make a new File and use it like this
$file2 = fopen("contacts2.csv", "w");
fputcsv($file2, $list[1]);
You always write in the same file here, because you are refering to $file
fputcsv($file, $list[1]);
I got a loop with whom I write data in a table, included urls of files I've to zip.
During the loop I put the url in an array.
At the end of table I would have a button, giving me the zip of all files.
I'm in a wordpress site, PHP 5 and Linux.
During loop I save url file here with its path
if (file_exists($file_letttut)) {
$nameAndCode['zipp'] = "http://mypath/to/".$file_letttut;
$namesArray[] = $nameAndCode;}
I tried different codes to zip, I write here the easier
$zip = new ZipArchive;
$zip_name = "zippot.zip"; // Zip name
$res = $zip->open($zip_name, ZipArchive::CREATE);
if ($res === TRUE) {
foreach($namesArray as $key => $value) {
$nomefile = basename($namesArray[$key][zipp].$value);
$nomefile = str_replace('Array', '', $nomefile);
$nomecompleto = str_replace('Array', '', $namesArray[$key][zipp].$value);
$zip->addFile($nomecompleto, $nomefile);
}
$zip->close();
echo 'ok';
} else {
echo 'failed';
}
if(file_exists($zip_name)) {
echo "yes";die;
header('Content-type: application/zip');
header('Content-Disposition: attachment; filename="'.$res.'"');
readfile($res);
unlink($res);
} else {
echo "zip not created";die;
}
$zip_name doesn't exist...
Where do I fail?
Should I've to copy files to a folder before?
Thanks in advance
I have on my website to grab 5 random files from all the files in my directory and all is going well but about %50 of the time I get a duplicate. I would like to:
1) Remove duplicate
2) Replace with new unique file
.. or maybe I can prevent duplicates in an easier manner all together? I tried to find a function for this without asking a question of here but I have not found one. Any ideas? Thanks!!
<?php
//define stuff
$dir = "uploads/";
$allfiles = array_diff(scandir($dir), array('.', '..'));
echo '<pre>';
print_r("all files ready for access");
echo '<pre>';
// create zip
$zip = new ZipArchive();
$zip_name = "zipfile.zip";
if($zip->open($zip_name, ZIPARCHIVE::CREATE)!==TRUE){
$error .= "* Sorry ZIP creation failed at this time";
}
else {
echo '<pre>';
print("created zip");
echo '<pre>';
}
// array of random files
$n=1;
while ($n<=6){
$n ++;
$file = array_rand($allfiles);
$randomfile = $allfiles[$file];
echo '<pre>';
print_r($randomfile);
echo '<pre>';
if (file_exists($dir.$randomfile)) {
$content = $dir.$randomfile;
echo '<pre>';
print_r($content);
echo '<pre>';
$zip->addfile($content,$randomfile);
echo 'ok';
} else {
echo 'failed';
}
}
//present for download
$zip->close();
ob_get_clean();
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private", false);
header("Content-Type: application/zip");
header("Content-Disposition: attachment; filename=" . basename($zip_name) . ";" );
header("Content-Transfer-Encoding: binary");
header("Content-Length: " . filesize($zip_name));
readfile($zip_name);
if(file_exists($zip_name))
{
unlink('zipfile.zip');
}
?>
Just check if you already found this file. And if you already found it, get a new one by continuing without incrementing $n.
Look at this:
// array of random files
$n = 1;
$myfiles = [];
while ($n<=6){
$file = array_rand($allfiles);
$randomfile = $allfiles[$file];
if(!in_array($randomfile, $myfiles)) { // this line checks if you already got this file
$myfiles[] = $randomfile;
} else {
continue; // if you already got it, continue (http://php.net/manual/de/control-structures.continue.php)
}
echo '<pre>';
print_r($randomfile);
echo '<pre>';
if (file_exists($dir.$randomfile)) {
$content = $dir.$randomfile;
echo '<pre>';
print_r($content);
echo '<pre>';
$zip->addfile($content,$randomfile);
echo 'ok';
} else {
echo 'failed';
}
$n++; // increment in the end
}
You can pass a second parameter to the array_randfunction:
$my_files = array_rand($allfiles, 5);
or shuffle the array and get -for example- the first five items:
shuffle($allfiles);
// now $allfiles[0...4] are 5 different files.
create a an array for the files already added to the zip :
$added = //array
$zip->addfile($content,$randomfile);
array_push($added,$randomfile)
and check any new file in the above array before inserting:
if(!in_array($randomfile, $added)){
//add the file to zip
}
I want to create a CSV file from my data. This is my loop:
foreach($animals as $row) {
$row['species'];
$row['name'];
$row['size']
}
This is how I create my CSV. So far this works:
$country = 'africa';
$newFileName = './files/'.$country.".csv";
$newFileContent = 'here should be my content';
if(file_put_contents($newFileName,$newFileContent)!=false) {
echo "File created (".basename($newFileName).")";
} else {
echo "Cannot create file (".basename($newFileName).")";
}
But I have a problem to create from my loop in a proper CSV format.
With the help of a tutorial I tried this:
$country = 'africa';
$newFileName = './files/'.$country.".csv";
$newFileContent = $animals;
foreach ($animals as $line) {
fputcsv($newFileName,explode(',',$line));
}
if(file_put_contents($newFileName,$newFileContent)!=false) {
echo "File created (".basename($newFileName).")";
} else {
echo "Cannot create file (".basename($newFileName).")";
}
But this is not working.
You need to open your file for writing first and grab the file handle:
$country = 'africa';
$newFileName = "./files/" . $country . ".csv";
$fileHandle = fopen($newFileName,"w"); // Open file for writing
foreach ($animals as $line){
fputcsv($fileHandle, explode(',',$line));
}
fclose($fileHandle); // Make sure we close file after finishing writing to it
Regarding the first foreach loop in your question $animals is an array containing arrays with keys species, name and size.
So you have to change
foreach ($animals as $line){
fputcsv($newFileName,explode(',',$line));
}
to
foreach ($animals as $line){
fputcsv($newFileName, array($line['species'], $line['name'], $line['size']));
}
because $line is already an array and should be exploded.
This is how I've always done it in the past.
$country = 'africa';
$fileName = "./files/" . $country . ".csv";
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header('Content-Description: File Transfer');
header("Content-type: text/csv");
header("Content-Disposition: attachment; filename={$fileName}");
header("Expires: 0");
header("Pragma: public");
$fh = #fopen( 'php://output', 'w' );
$headerDisplayed = false;
foreach ( $animals as $line ) {
// Add a header row if it hasn't been added yet
if ( !$headerDisplayed ) {
// Use the keys from $line as the titles
fputcsv($fh, array_keys($line));
$headerDisplayed = true;
}
// Put the data into the stream
fputcsv($fh, $line);
}
// Close the file
fclose($fh);
// Make sure nothing else is sent, our file is done
exit;