How can I remove duplicates and add a new unique file? - php

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
}

Related

Create an array of files to add in zip?

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

Add both folders and files into zip (PHP)

I am looking to add both folders and files from a matching array to a zip file. Below is my code:
function listdir($start_dir='./assets') {
//Array that will contain the director
$files = array();
if (is_dir($start_dir)) {
$fh = opendir($start_dir);
while (($file = readdir($fh)) !== false) {
// Loop through the files, skipping '.' and '..', and recursing if necessary
if (strcmp($file, '.')==0 || strcmp($file, '..')==0) continue;
$filepath = $start_dir . '/' . $file;
if ( is_dir($filepath) )
$files = array_merge($files, listdir($filepath));
//else
array_push($files, $filepath);
}
closedir($fh);
} else {
// false if the function was called with an invalid non-directory argument
$files = false;
}
return $files;
}
//Array of all files
$allFiles = listdir('./assets');
print_r($allFiles);
//Gets all values with name "asset"
$name = $_POST['asset'];
//If there are items in the array, zip them together
if($name!=0){
//Compares $_POST array with array of all files in directory
$result = array_intersect($allFiles, $name);
function zipFilesAndDownload($result){
$zip = new ZipArchive();
//create the file and throw the error if unsuccessful
if ($zip->open('SelectedAssets.zip', ZIPARCHIVE::CREATE )!==TRUE) {
exit("cannot open SelectedAssets.zip\n");
}
//add each files of $file_name array to archive
foreach($result as $allFiles) {
$zip->addFile($allFiles);
}
$zip->close();
$zipped_size = filesize('SelectedAssets.zip');
header("Content-Description: File Transfer");
header("Content-type: application/zip");
header("Content-Type: application/force-download");// some browsers need this
header("Content-Disposition: attachment; filename=SelectedAssets.zip");
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header("Content-Length:". " $zipped_size");
ob_clean();
flush();
readfile("SelectedAssets.zip");
unlink("SelectedAssets.zip"); // Now delete the temp file (some servers need this option)
exit;
}
if(isset($_POST['submit'])) {
//$file_names=$_POST['assets'];// Always sanitize your submitted data!!!!!!
//$file_names = filter_var_array($_POST['assets']);//works but it's the wrong method
$filter = filter_input_array(INPUT_POST, FILTER_SANITIZE_SPECIAL_CHARS) ;
$file_names = $filter['assets'] ;
//Archive name
$archive_file_name='DEMO-archive.zip';
//Download Files path
$file_path= getcwd(). './';
//call the function
zipFilesAndDownload($result);
} else {
print 'Something went wrong.';
exit;
}
} //Otherwise, don't.
else {
print_r("Please select a file.");
}
The code above searches through a directory and reads all the folders and files. Then using array_intersect I matched files that were put into an empty array by the user to all the files in the previously searched directory. I then zip the files that match and download.
My question is, how can I have a folder be added to this zip as well? As of now, this only adds files and folders are assumed as empty.

How can I create a CSV file in a directory and store data from my loop in a proper format?

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;

how to archive download multiple files from database in php

Actually i got the zipfile. But i did't need total files from the table.i want to selected userid files... I try to code bellow, i used php and mysql.
<?php
function zipFilesAndDownload($file_names,$archive_file_name,$file_path)
{
$zip = new ZipArchive();
if ($zip->open($archive_file_name, ZIPARCHIVE::CREATE )!==TRUE) {
exit("cannot open <$archive_file_name>\n");
}
foreach($file_names as $files)
{
$zip->addFile($file_path.$files,$files);
//echo $file_path.$files,$files."<br />";
}
$zip->close();
header("Content-type: application/zip");
header("Content-Disposition: attachment; filename=$archive_file_name");
header("Pragma: no-cache");
header("Expires: 0");
readfile("$archive_file_name");
exit;
}
require_once("config.php");
$cqurfetch=mysql_query("SELECT * FROM albums where user_id='$user_id' and accept='1'");
while($row = mysql_fetch_array($cqurfetch))
{
$file_names[] = $row['user_album_images'];
}
$archive_file_name=time().'.gallery.zip';
$file_path="/uploads/";
zipFilesAndDownload($file_names,$archive_file_name,$file_path);
?>
After Many trails i have got one answer for your question.
Only 'user_id' files are zipped and stored in that zip folder.
Example:-
<?php
require_once("config.php");
$user_id = 49 ; //Just For your reference
$accept = 1 ; //Just For your reference
$sql = "SELECT * FROM albums where user_id='$user_id' and accept='$accept'";
$result = $con->query($sql);
if ($result->num_rows > 0) {
// output data of each row
while($row = $result->fetch_assoc()) {
$array[] = $row["user_album_images"];
echo "user_album_images: " .$row["user_album_images"]. "<br>"; //This is also just for your reference
}
}
else{
echo "fail";
}
$file= "/uploads/gallery.zip"; //Zip file path
$zip = new ZipArchive;
echo "*****zip started.*****\n";
if ($zip->open($file, ZipArchive::CREATE) === TRUE) {
foreach($array as $key => $value)
{
$zip->addFile("/".$value);
}
$zip->close();
echo '^^^^^^Zip ended^^^^^^';
}
?>
I have tested this code in my local system,this is working as like your requirement.
Hope this helps

file exist in php download

I'm download file but i want. IF file exist from drive C i can download,
ELSE IF file exist automatic can donwload file from drive D . Else "File Not Found"
i'm confused :(
This is my quoute script
$id = $_GET['id'];
$query = "SELECT * FROM upload WHERE id = '$id'";
$jl = mysql_query($query);
$data = mysql_fetch_array($jl);
header("Content-Disposition: attachment; filename=".$data['name']);
header("Content-length: ".$data['size']);
header("Content-type: ".$data['type']);
$filename = $data['name'];
if (file_exists($filename)) {
$fp = fopen("d:/result/".$data['name'], 'r');
$content = fread($fp, filesize('d:/result/'.$data['name']));
fclose($fp);
}
else if (file_exists($filename)) {
$fp = fopen("c:/result/".$data['name'], 'r');
$content = fread($fp, filesize('c:/result/'.$data['name']));
fclose($fp);
}
else {
echo "File Not Found";
}
// show file download
echo $content;
exit;
You could specify the list of paths in an array.
$paths ['c:/result/', 'd:/result/];
then you loop through these paths:
foreach($paths as $path){
if(file_exists($path.$data['name'])){
print file_get_contents($path.$data['name']);
}
}
Full solution for you:
//prevent sql injection
$data = mysql_fetch_array(mysql_query("SELECT * FROM upload WHERE id = '".intval($_GET['id'])."'"));
//now you can add as much paths as you like
$paths = [
'd:/result/',
'c:/result/'
];
foreach ($paths as $path) {
if (file_exists($path . $data['name'])) {
header("Content-Disposition: attachment; filename=" . $data['name']."; ".
"Content-length: " . $data['size']."; ".
"Content-type: " . $data['type']);
print file_get_contents($path . $data['name']);
exit;
}
}
echo "File not found";
exit;
Your code is backwards. You've output your content headers already, so if the file doesn't exist, your user will be downloading a file whose contents are "File Not Found". That'd just confuse them when they double-click on their pdf/word/whatever file and get a "file is corrupted" error.
Your code should be more like:
$c_source = 'C:/...';
$d_source = 'D:/...';
if (is_readable($c_source)) {
header(...); // <--do this only if you found a file
readfile($c_source);
} else if (is_readable($d_source)) {
header(...); // do this only if you found a file
readfile($d_source);
} else {
die("File not found");
}

Categories