Looping inside foreach till first matched element is found - php

First of all apologies for the vague question title. I couldn't come up with a title that made sense.
I'm looping through image files in a directory using:
$folder = 'frames/*';
foreach(glob($folder) as $file)
{
}
The Requirement
I want to measure each file's size and if it's size is less then 8kb, move to the next file and check it's size and do so until you get the file whose size is greater than 8kb. Right now I'm using
$size = filesize($file);
if($size<8192) // less than 8kb file
{
// this is where I need to keep moving until I find the first file that is greater than 8kb
// then perform some actions with that file
}
// continue looping again to find another instance of file less than 8kb
I had a look at next() and current() but couldn't come up with a solution that I was looking for.
So for a result like this:
File 1=> 12kb
File 2=> 15kb
File 3=> 7kb // <-- Found a less than 8kb file, check next one
File 4=> 7kb // <-- Again a less than 8kb, check next one
File 5=> 7kb // <-- Damn! a less than 8kb again..move to next
File 6=> 13kb // <-- Aha! capture this file
File 7=> 12kb
File 8=> 14kb
File 9=> 7kb
File 10=> 7kb
File 11=> 17kb // <-- capture this file again
.
.
and so on
UPDATE
The complete code that I'm using
$folder = 'frames/*';
$prev = false;
foreach(glob($folder) as $file)
{
$size = filesize($file);
if($size<=8192)
{
$prev = true;
}
if($size=>8192 && $prev == true)
{
$prev = false;
echo $file.'<br />'; // wrong files being printed out
}
}

What you need to do is keep a variable indicating if the previous analyzed file was a small one or a big one and react accordingly.
Something like this :
$folder = 'frames/*';
$prevSmall = false; // use this to check if previous file was small
foreach(glob($folder) as $file)
{
$size = filesize($file);
if ($size <= 8192) {
$prevSmall = true; // remember that this one was small
}
// if file is big enough AND previous was a small one we do something
if($size>8192 && true == $prevSmall)
{
$prevSmall = false; // we handle a big one, we reset the variable
// Do something with this file
}
}

Related

while loop with operator++ only counting up once

I adopted code from https://stackoverflow.com/a/44553006/8719001
but can't figure out why when uploading the same file "test.jpg" several times it only counts up once, creating "test-1.jpg" but not more ie. test-2.jpg, test-3.jpg.
Can anybody spot the issue and help please?
$keepFilesSeperator = "-";
$keepFilesNumberStart = 1;
if (isset($_FILES['upload'])) {
// Be careful about all the data that it's sent!!!
// Check that the user is authenticated, that the file isn't too big,
// that it matches the kind of allowed resources...
$name = $_FILES['upload']['name'];
//If overwriteFiles is true, files will be overwritten automatically.
if(!$overwriteFiles)
{
$ext = ".".pathinfo($name, PATHINFO_EXTENSION);
// Check if file exists, if it does loop through numbers until it doesn't.
// reassign name at the end, if it does exist.
if(file_exists($basePath.$name))
{
$operator = $keepFilesNumberStart;
//loop until file does not exist, every loop changes the operator to a different value.
while(file_exists($basePath.$name.$keepFilesSeperator.$operator))
{
$operator++;
}
$name = rtrim($name, $ext).$keepFilesSeperator.$operator.$ext;
}
}
move_uploaded_file($_FILES["upload"]["tmp_name"], $basePath . $name);
}
your while loop condition has a problem
while( file_exists( $basePath.$name.$keepFilesSeperator.$operator ) )
the $name variable still contains the full name of file, in this case test.jpg, you're testing a value like /home/test.jpg-1 so finally the while loop is never executed as the file test.jpg-1 never exists, that's why you always get the test-1.jpg on disk and not a ...-2.jpg or ...-3.jpg

How to delete the next file in php

Let's say I have a folder containing 99tf.txt, 40.txt, 65.txt , in any order
If the current script var is 40.txt: I would like it to delete 65.txt (or the next file)
I was looking into something like that:
$file='40.txt';
if ($handle = opendir('./log/')) {
$entry= readdir($handle);
//move pointer to 40.txt
while ($file != $entry && $entry !== false) {
$entry = readdir($handle)
}
//go to the next file
$entry = readdir($handle)
if(is_file('./log/'.$entry)){
unlink('./log/'.$entry);
}
}
But I would like to avoid to go into a loop each time since there could be a lot of files in the folder.
So is there a way to change the $handle pointer to the '$file' directly and delete the next file?
If you don't mind using scandir, then this should work better for you.
$file = '40.txt';
$contents = scandir('./log/');
// Should already be sorted, but do again for safe measure
sort($contents);
// Make sure the file is in there.
if (false !== $index = array_search($file, $contents)) {
// If the file is at the end, do nothing.
if ($index !== count($contents)) {
// Remove the next index
unlink('./log/' . $contents[$index + 1]);
}
}
In regard to the order not mattering, you don't need to sort it. Worth noting however, is that your method, takes longer, but uses less memory, while this method is the reverse, much faster, but potentially more memory consumption.
<?php
$file = '40.txt';
$scan_folder = scandir('./log/');
$num_files = count($scan_folder);
if ($num_files > 1) {
$file_key = array_search($file, $scan_folder) +1;
unlink('./log/'.$file_key);
} else {
// here you will preserve only 1 file all others can be removed every time this script is executed
}
?>

How can I check that at-least one file is selected for upload

how can I check that user has selected at-least one file for upload in below code ?
i have tried with in_array, isset, !empty functions but no success
please note that userfile input is array in html
if(!empty($_FILES['userfile']['tmp_name'])){
$upload_dir = strtolower(trim($_POST['name']));
// Create directory if it does not exist
if(!is_dir("../photoes/". $upload_dir ."/")) {
mkdir("../photoes/". $upload_dir ."/");
}
$dirname = "../photoes/".$upload_dir;
for($i=0; $i < count($_FILES['userfile']['tmp_name']);$i++)
{
// check if there is a file in the array
if(!is_uploaded_file($_FILES['userfile']['tmp_name'][$i]))
{
$messages[] = 'No file selected for no. '.$i.'field';
}
/*** check if the file is less then the max php.ini size ***/
if($_FILES['userfile']['size'][$i] > $upload_max)
{
$messages[] = "File size exceeds $upload_max php.ini limit";
}
// check the file is less than the maximum file size
elseif($_FILES['userfile']['size'][$i] > $max_file_size)
{
$messages[] = "File size exceeds $max_file_size limit";
}
else
{
// copy the file to the specified dir
if(#copy($_FILES['userfile']['tmp_name'][$i],$dirname.'/'.$_FILES['userfile']['name'][$i]))
{
/*** give praise and thanks to the php gods ***/
$messages[] = $_FILES['userfile']['name'][$i].' uploaded';
}
}
}
}else{
$messages[] = 'No file selected for upload, Please select atleast one file for upload';
dispform();
}
Here's how I do it its a couple of if's and I use a for loop as I allow multiple file uploads from a single drop down but its the if's that are more important to you
$uploaded = count($_FILES['userfile']['name']);
for ($i=0;$i<$uploaded;$i++) {
if (strlen($_FILES['userfile']['name'][$i])>1) {
// file exists so do something
} else {
//file doesn't exist so do nothing
}
}
You'll note I compare against the name element of the global $_FILES this is because you should never be able to upload a file without a name which also applies for no file uploaded
Don't do it client side thats a dumb place to do validation as the user can simply turn js processing off in the browser or it can be blocked by certain addons etc or intercepted and altered via firebug and various browser search hijacking toolbars etc.
Anything like this should always be done server side!
finally I found the answer, I am giving it here for other users,
I have 5 keys in html input array so array index is up to 4
if(!empty($_FILES['userfile']['tmp_name'][0]) or !empty($_FILES['userfile']['tmp_name'][1]) or !empty($_FILES['userfile']['tmp_name'][2]) or !empty($_FILES['userfile']['tmp_name'][3]) or !empty($_FILES['userfile']['tmp_name'][4])){
//at-least one file is selected so proceed to upload
}else{
//no file selected, notify user
}
There are several methods of doing this with PHP (e.g. Check if specific input file is empty), but with JS it's faster and less expensive on the server. Using jQuery you can do this:
$.fn.checkFileInput = function() {
return ($(this).val()) ? true : false;
}
if ($('input[type="file"]').checkFileInput()) {
alert('yay');
}
else {
alert('gtfo!');
}

Downloading files from server

In my project I have a code for downloading images from a server. In php code I have:
if (is_dir($dir)){ //check if is directory
$files = scandir($dir); //list files
$i=-1;
$result = array();
foreach($files as $file){
$file = $dir.$file; //complete dir of file
if(is_file($file)){ //if it's a file
$i++;
$fileo = #fopen($file,"rb"); //open and write it on $result[$i]
if ($fileo) {
$result[$i] = "";
while(!feof($fileo)) {
$result[$i] .= fread($fileo, 1024*8);
flush();
if (connection_status()!=0) {
#fclose($fileo);
die();
}
}
$result[$i] = utf8_encode($result[$i]); //This prevents null returning on jsonencode
#fclose($fileo);
}
}
}
}else{
echo json_encode(array('Error'));
}
echo json_encode($result); //returns images as an array of strings, each one with all code of an image.
And in java I have an httpost method with asynctask. The problem of this is that I need to wait until all images are downloaded. I have thought that maybe I can download an image with a number and if the number is 0 for example recall to the server to download the next image but I think that maybe is a waste of time calling again the server and listing files again. Is there a better way so I can download image per image instead of all at the same time without calling N times to the sever?
I've had the same problem that you are having, and my solution was the next:
1º Download all data you need
2º Download to the computer the image web direction
3º Execute an asynctask per Image to download it and update your Activity while is needed
Maybe i'm not so exact and i would need some more details to give a better solution.

move_uploaded_file moves the file into destination, but returns false, why?

I'm facing a strange situation here: I have an advanced multipart file upload script, which, for example, checks for duplicate filenames by scanning the destination folder and then renames the duplicate names with iteration number. Now, the problem here is, that for some reason, script passess with green lights if no duplicates are submitted, but if duplicate is inputted, script will return false in move_upload_file part, but however, still manage to create the proper duplicate into destination folder. I was just wondering, why and how the move_upload_file function returns false, but still proceeds moving the file?
Here is simplified snippet of the script, just trying to point you out to the problem:
<?php
//I'll loop all the files, which are submitted (in array)
foreach($_FILES['myFiles']['tmp_name'] as $key => $tmp_path) {
//Alot of stuff (most likely unrelated) happens here
//filepath contains both destination folder and filename
$filepath = $destination_folder.$filename;
if (file_exists($filepath)) {
$duplicate_filename = true;
//Some more stuff happens here. Then comes the actual moving part. Before this we have found duplicates
//for this upload file and counted proper duplicate value.
$file_increment = $num_of_filename_duplicates + 1;
while ($duplicate_filename == true) {
if(file_exists($filepath)) {
//Separate filename parts and make new duplicate name with increment value
$info = pathinfo($filename);
$basename = basename($filename,'.'.$info['extension']);
$newfilename = $basename."(".$file_increment.").".$info['extension'];
$filepath = $destination_folder.$newfilename;
//Now, this returns me false, but still creates the file into destination
if(move_uploaded_file($tmp_path, $filepath)) {
$file_success = true;
$file_increment++;
}
//So thats why this is true and I'll get the file_error
else {
$file_error = "File error: Uploading of the file failed.";
break;
}
}
else {
$duplicate_filename = false;
}
}
}
}
?>
The only reasons can be:
1) If filename is a valid upload file, but cannot be moved for some
reason, no action will occur, and move_uploaded_file() will return
FALSE. Additionally, a warning will be issued.
2) If filename is not a valid upload file, then no action will occur, and
move_uploaded_file() will return FALSE.
Your case seems to be 2. Try to set the following at the top of your script to see errors:
error_reporting(E_ALL);
ini_set("display_errors", 1);
Don't try to find some magic. Just debug your code.

Categories