Use opendir one time instead of using it in for loop - php

I have below code to get content from remote directory.
$dirHandle = opendir("ssh2.sftp://$sftp/".PATH_OUT);
while (false !== ($file = readdir($dirHandle))) {
// something...
}
Now, the thing is, above code is in forloop. when I put $dirHandle = opendir("ssh2.sftp://$sftp/".PNB_PATH_OUT); outside of forloop then it gives me required result only for first record. So, obviously it's readdir is not working for second record in forloop.
How can I do this in such a way that I need to use opendir only once and use that connection more than 1 time?
Required Solution
$dirHandle = opendir("ssh2.sftp://$sftp/".PATH_OUT);
for(...){
while (false !== ($file = readdir($dirHandle))) {
// something...
}
}

Your while loop is traversing the entire directory until there are no more files, in which case readdir returns false. Therefore any time readdir is called after the first traversal, it will just return false because it is already at the end of the directory.
You could use rewinddir() in the for loop to reset the pointer of the directory handle to the beginning.
$dirHandle = opendir("ssh2.sftp://$sftp/".PATH_OUT);
for(...){
rewinddir($dirHandle);
while (false !== ($file = readdir($dirHandle))) {
// something...
}
}
Since the sftp stream appears to not support seeking, you should just store the results you need and do the for loop after the while loop. You are, after all, traversing the same directory multiple times.
$dirHandle = opendir("ssh2.sftp://$sftp/".PATH_OUT);
while (false !== ($file = readdir($dirHandle))) {
$files[] = $file;
}
for(...){
// use $files array
}

Related

get image files from directory on server for further processing

I have folders on the server that contain image files. I'm trying to get those files and then upload them further, but I think I'm using the wrong function.
My code:
$dir = "../uploads/".$folderimage."/";
if ($handle = opendir($dir)) {
while (false !== ($entry = readdir($handle))) {
if ($entry != "." && $entry != "..") {
echo "$entry\n";
$handle = fopen($entry,"wb");
$mug->images_upload(array( "AlbumID" => "#####", "File" => $handle));
}
}
closedir($handle);
}
Not sure what I am doing, all I need to do is pass the file to the class function $mug->images->upload. It works from a $_POST request but I need to move the files already uploaded to the folder.
It's a bit tricky to emulate a file upload POST request for your $mug object. You would be better off if you could refactor the code in $mug as follows:
$mug fetches the uploaded file and puts it to its destination place.
You create a new function that implements the processing you wish to use here and in $mug.
Call this function from here, and from $mug with the appropriate filename.
If $mug->images_upload is expecting the file path then pass $dir.$entry to it
<?php
$dir = "../uploads/".$folderimage."/";
if ($handle = opendir($dir)) {
while (false !== ($entry = readdir($handle))) {
if ($entry != "." && $entry != "..") {
echo $entry.PHP_EOL;
$mug->images_upload(array( "AlbumID"=>"#####", "File"=>$dir.$entry));
}
}
closedir($handle);
}
//Or simpler way but slightly slower
foreach (glob($dir."*.{png,jpg,gif}", GLOB_BRACE) as $file) {
echo $file.PHP_EOL;
$mug->images_upload(array( "AlbumID"=>"#####", "File" =>$dir.$file));
}
?>
There are a number of apparent issues with the code that you have posted.
$dir = "../uploads/".$folderimage."/";
if ($handle = opendir($dir)) {
while (false !== ($entry = readdir($handle))) {
if ($entry != "." && $entry != "..") {
echo "$entry\n";
$handle = fopen($entry,"wb");
$mug->images_upload(array( "AlbumID" => "#####", "File" => $handle));
}
}
closedir($handle);
}
Clashing variables.
You have used the $handle vairable to store the directory handle, only to later overwrite it with a file resource inside the loop. As soon as you overwrite it inside the loop, the next call to readdir($handle) does not make any sense are you are calling the function on a file resource. This could very easily lead to an infinite loop since when readdir() is given rubbish, it might return NULL.
Incorrect path for fopen()
Given $folderimage = "images" and $entry = "photo.jpg", then the fopen() line will try to open the image at photo.jpg rather than ../uploads/images/photo.jpg. You likely wanted to use something like $dir . $entry, but read on as you shouldn't be using fopen() at all.
Incorrect usage of the phpSmug library
The File argument must be a string containing "the path to the local file that is being uploaded" (source). You instead try to pass a file resource from fopen() to it.
opendir()/readdir() for directory iteration is ancient
There are better ways to traverse directory contents in PHP. As mentioned in Lawrence's answer, glob() might be useful.
I would also advocate using the filesystem iterator from the SPL.
$dir = "../uploads/$folderimage/";
foreach (new FilesystemIterator($dir) as $fileinfo) {
$image_pathname = $fileinfo->getPathname();
$mug->images_upload("AlbumID=#####", "File=$image_pathname");
}

PHP Zend Framework S3 - PutFile not putting

I'm simply trying to loop through a folder of images and put them in an Amazon S3 bucket. I just can't figure out why it doesn't like the DATA part of the PUTFILE function.
If I try:
$res = $s3 -> putFile("test-bucket/".$entry);
It creates a blank file (0 bytes) in the bucket, so I know it's connecting OK, and the filenames are correct also. I've also tried looping through the folders files and echoing the filenames to the screen, without using the Zend S3 function, which proved this page can access the files behind root.
The documentation regarding this function says:
putFile($path, $object, $meta) puts the content of the file in $path
into the object named $object.
The optional $meta argument is the same as for putObject. If the
content type is omitted, it will be guessed basing on the source file
name.
This is what I've tried:
if ($handle = opendir('d:/web-library-photos/temp-previews')) {
$loopCounter = 0;
while (false !== ($entry = readdir($handle))) {
///
$loopCounter = $loopCounter + 1;
if ($loopCounter < 3) { // for test purposes only
$localPath = "d:/web-library-photos/temp-previews/".$entry;
$s3 = new Zend_Service_Amazon_S3($aws_access_key_id, $aws_s3_secret);
$res = $s3 -> putFile($localPath, "test-bucket/".$entry);
echo "Success for ".$entry.": " . ($res ? 'Yes' : 'No') . "<br>";
}
///
}
closedir($handle);
}
This particular "try" yields the error:
Cannot read file d:/web-library-photos/temp-previews/.' in C:\Inetpub\vhosts\.....thispage.php
So I thought I would try file_get_contents() and readfile() but still no luck!
Please, please, put me straight on this one - it's driving me round the bend.
UPDATE
Right, I have a clue what's wrong but not how to solve it.
If I simply do this:
if ($handle = opendir('d:/web-library-photos/temp-previews')) {
while (false !== ($entry = readdir($handle))) {
echo $entry."<BR>";
}
closedir($handle);
}
I get a . and a .. at the beginning of my results, which obviously can't be read as filenames!! What is going on here, how do I get around it?
Try to append this in while (false !== ($entry = readdir($handle)))
while (false !== ($entry = readdir($handle))) {
if($entry == "." || $entry == "..") continue;
/* other codes */
}

PHP: How can I grab a single file from a directory without scanning entire directory?

I have a directory with 1.3 Million files that I need to move into a database. I just need to grab a single filename from the directory WITHOUT scanning the whole directory. It does not matter which file I grab as I will delete it when I am done with it and then move on to the next. Is this possible? All the examples I can find seem to scan the whole directory listing into an array. I only need to grab one at a time for processing... not 1.3 Million every time.
This should do it:
<?php
$h = opendir('./'); //Open the current directory
while (false !== ($entry = readdir($h))) {
if($entry != '.' && $entry != '..') { //Skips over . and ..
echo $entry; //Do whatever you need to do with the file
break; //Exit the loop so no more files are read
}
}
?>
readdir
Returns the name of the next entry in the directory. The entries are returned in the order in which they are stored by the filesystem.
Just obtain the directories iterator and look for the first entry that is a file:
foreach(new DirectoryIterator('.') as $file)
{
if ($file->isFile()) {
echo $file, "\n";
break;
}
}
This also ensures that your code is executed on some other file-system behaviour than the one you expect.
See DirectoryIterator and SplFileInfo.
readdir will do the trick. Check the exampl on that page but instead of doing the readdir call in the loop, just do it once. You'll get the first file in the directory.
Note: you might get ".", "..", and other similar responses depending on the server, so you might want to at least loop until you get a valid file.
do you want return first directory OR first file? both? use this:
create function "pickfirst" with 2 argument (address and mode dir or file?)
function pickfirst($address,$file) { // $file=false >> pick first dir , $file=true >> pick first file
$h = opendir($address);
while (false !== ($entry = readdir($h))) {
if($entry != '.' && $entry != '..' && ( ($file==false && !is_file($address.$entry)) || ($file==true && is_file($address.$entry)) ) )
{ return $entry; break; }
} // end while
} // end function
if you want pick first directory in your address set $file to false and if you want pick first file in your address set $file to true.
good luck :)

php sorted array and readfile not reading in order

I am trying to write a php function to save and then display comments on an article.
In my save.php, I am formulating the file with:
$file = "article1/comments/file".time().".txt";
Then using fwrite() to write to a directory.
In my index I have:
if ($handle = opendir('article1/comments')) {
while (false !== ($file = readdir($handle))) {
if ($file != "." && $file != "..") {
$files = array($file);
sort($files);
foreach($files as $comments){
echo "<div class='message'>";
readfile('article1/comments/'.$comments);
echo "&lt/div>";
}
}
}
closedir($handle);
}
For the most part this displays the comments in the correct order, but for some reason, some files are displaying out of order. Furthermore, if I change sort() to rsort(), there is no change in how they are displayed.
I presume this is because readfile() is not following the sorted array's order. So I am wondering for one, why readfile does not display the files in order from newest to oldest, and two, how can I make it display them correctly?
Thanks.
edit: I copied the directory of comments from the live site to my local xampp installation, and the comments are displayed in order locally, but using the same code on my site results in comments not being in order.
Take a look at DirectoryIterator, make sure to check 1st comment for DirectoryIterator's isFile() method, it should be enough to solve this question.
Try this:
$files = array();
if ($handle = opendir('article1/comments')) {
while (false !== ($file = readdir($handle))) {
if ($file != "." && $file != "..") {
$files[] = $file; //adding file to array
}
}
closedir($handle);
}
//if array is not empty-check (can go here)
if(count($files)>0) {
sort($files);
foreach($files as $comments){
echo "<div class='message'>";
readfile('article1/comments'.$comments);
echo "</div>";
}//~foreach
}//~if
Please, use any database for this stuff! Don't use files! This is not realy secure and has low performance

PHP List Images In Folder

I have the following code
// Define the full path to your folder from root
$path = "../galleries/".$album;
// Open the folder
$dir_handle = #opendir($path) or die("Unable to open $path");
// Loop through the files
while ($file = readdir($dir_handle)) {
if(strlen($file)>1){echo "<a href='http://minification.com/?page_id=32&dir=$album&img=$file'><img src='http://minification.com/galleries/$album/$file'></a>";}
}
// Close
closedir($dir_handle);
What i want to do is pull in all the images from a folder and display them using PHP. So far its working up to the point where it only displays one image out of the folder. Anyone know how to fix this?
Your second file probably evaulates to false, see readdir(), you should do:
while (false !== ($file = readdir($dir_handle))) {
Hint: If this is PHP 5, you can reduce the hassle a bit by using scandir instead.
try this:
while(false !== ($file = readdir($handle))) {
A lot of different values evaluate to false in php so you may be getting a false positive.

Categories