Foreach?

I use this bit of code to handle 1 image being uploaded


 $allowedExts = array("jpg", "jpeg", "gif", "png");
  $extension = end(explode(".", $_FILES["file"]["name"]));
  if ((($_FILES["file"]["type"] == "image/gif")
  || ($_FILES["file"]["type"] == "image/jpeg")
  || ($_FILES["file"]["type"] == "image/png")
  || ($_FILES["file"]["type"] == "image/pjpeg"))
  && ($_FILES["file"]["size"] < 200000)
  && in_array($extension, $allowedExts))
    {
    if ($_FILES["file"]["error"] > 0)
      {
      echo "Return Code: " . $_FILES["file"]["error"] . "<br>";
      }
    else
      {
      echo "Upload: " . $_FILES["file"]["name"] . "<br>";
      echo "Type: " . $_FILES["file"]["type"] . "<br>";
      echo "Size: " . ($_FILES["file"]["size"] / 1024) . " kB<br>";
      echo "Temp file: " . $_FILES["file"]["tmp_name"] . "<br>";
  
      if (file_exists("uploads/" . $_FILES["file"]["name"]))
        {
        echo $_FILES["file"]["name"] . " already exists. ";
        }
      else
        {
        move_uploaded_file($_FILES["file"]["tmp_name"],
        "uploads/" . $_FILES["file"]["name"]);
        echo "Stored in: " . "uploads/" . $_FILES["file"]["name"];
        }
      }
    }
  else
    {
    echo "Invalid file";
    }

But now I have 6 images being uploaded and thing a foreach loop is best used here, ( How do I?)

Thanks…

If you want to upload from the input fields that you mentioned in your recent “looping” thread then it would be best if you changed the name of all input fields to use square brackets, which will make the value accessible as array in php:


<input type='file' name='file[]' id='file1'>
<input type='file' name='file[]' id='file2'>
...etc.

Then use this:


foreach ($_FILES["file"] as $file) {
  // code for uploading a single file
  // ...
}

After changing the input name to file[], use print_r($_FILES) in your php code to see how the array is structured and from there you will be able to adapt your code accordingly.

BTW, for better security of you should change the way you check the allowed file types. The “type” available in $_FILES is set by the browser and can’t be fully trusted. If you want to allow images only, then use getimagesize() on the file and read the file type from its result. This is much more secure. Suppress errors using @getimagesize() and if this function fails (returns false) then reject the file altogether since it’s not a valid image then.

Now you can control how many pictures your user uploads:
in this example it would be 4:

some javascript:

<script type="text/javascript">
var totalItems = 0;
function addItems()
{
if(totalItems < 3) {
var table1 = document.getElementById('tab1');
var newrow = document.createElement("tr");
var newcol = document.createElement("td");
var input = document.createElement("input");
input.type="file";
input.name="image[]";
newcol.appendChild(input);
newrow.appendChild(newcol);
table1.appendChild(newrow);
totalItems++;
} else {
//Display your message here..
}
}


function remItems()
{
   var table1 = document.getElementById('tab1');
   var lastRow = table1.rows.length;
   if(lastRow>=2) {
     table1.deleteRow(lastRow-1);
     totalItems--;
    }
}

    </script>


<tr  >
          <table align="center" border="0" id="tab1" >
            <tr>
              <td width="218" align="center"><input type="file" name="image[]" /></td>
              <td width="54" align="center"><  style="cursor:pointer" onclick="addItems()" /></td>
              <td><  style="cursor:pointer" onclick="remItems()" /></td>
            </tr>
          </table>
          <table align="center" border="0" id="tab2">
          </table>
        </tr>
// PICTURE UPLOAD SYSTEM
    $img=$_FILES["image"]["name"];
    foreach($img as $key => $value)
    {
    $name=$_FILES["image"]["name"][$key] ;
    $tname=$_FILES["image"]["tmp_name"][$key];
    $size=$_FILES["image"]["size"][$key];
    $oext=getExtention($name);
    $ext=strtolower($oext);
    $base_name=getBaseName($name);
	
   	//Rename image
		$new_name = $id."_".$key.".".$oext;
		$new_base_name = $id."_".$key;
		
    if($ext=="jpg" || $ext=="jpeg" || $ext=="bmp" || $ext=="gif"){
    if($size< 1024*1024){
	$image_path = "upload/".$new_name;
    if(file_exists($image_path)){
    move_uploaded_file($tname,$image_path);
    $result = 1;
    list($width,$height)=getimagesize($image_path);
    }
    else{
    move_uploaded_file($tname,$image_path);
    $result = 1;
    list($width,$height)=getimagesize($image_path);
	
 	then insert into database the way you want it to be!!
	INSERT INTO img VALUES ('', '$image_path', '$new_base_name', '$ext', '$height', '$width', '$size')");
	

I followed lemon juices suggestion (no offense chejug, but isn’t JavaScript not to reliable as it can be turned off?)
So, Heres what im getting
Warning: explode() expects parameter 2 to be string, array given in /home/fixmy1/public_html/masterasp/providers/thanks.php on line 42

Warning: end() expects parameter 1 to be array, null given in /home/fixmy1/public_html/masterasp/providers/thanks.php on line 42
Invalid file
Warning: explode() expects parameter 2 to be string, array given in /home/fixmy1/public_html/masterasp/providers/thanks.php on line 42

Warning: end() expects parameter 1 to be array, null given in /home/fixmy1/public_html/masterasp/providers/thanks.php on line 42
Invalid file
Warning: explode() expects parameter 2 to be string, array given in /home/fixmy1/public_html/masterasp/providers/thanks.php on line 42

Warning: end() expects parameter 1 to be array, null given in /home/fixmy1/public_html/masterasp/providers/thanks.php on line 42
Invalid file
Warning: explode() expects parameter 2 to be string, array given in /home/fixmy1/public_html/masterasp/providers/thanks.php on line 42

Warning: end() expects parameter 1 to be array, null given in /home/fixmy1/public_html/masterasp/providers/thanks.php on line 42
Invalid file
Warning: explode() expects parameter 2 to be string, array given in /home/fixmy1/public_html/masterasp/providers/thanks.php on line 42

Warning: end() expects parameter 1 to be array, null given in /home/fixmy1/public_html/masterasp/providers/thanks.php on line 42
Invalid file[B]
but this is what happens when I


echo "<pre>";
print_r($_FILES);
echo "</pre>";

[/B]


<pre>Array (     [file] => Array         (             [name] => Array                 (                     [0] => logo.gif                     [1] =>                      [2] =>                      [3] => signs.png                     [4] =>                      [5] =>                  )              [type] => Array                 (                     [0] => image/gif                     [1] =>                      [2] =>                      [3] => image/png                     [4] =>                      [5] =>                  )              [tmp_name] => Array                 (                     [0] => /tmp/phpyIfS3A                     [1] =>                      [2] =>                      [3] => /tmp/phpBDNY6b                     [4] =>                      [5] =>                  )              [error] => Array                 (                     [0] => 0                     [1] => 4                     [2] => 4                     [3] => 0                     [4] => 4                     [5] => 4                 )              [size] => Array                 (                     [0] => 6258                     [1] => 0                     [2] => 0                     [3] => 91631                     [4] => 0                     [5] => 0                 )          )  ) </pre>

heres the foreach loop


foreach ($_FILES["file"] as $file) {
 $allowedExts = array("jpg", "jpeg", "gif", "png");
  $extension = end(explode(".", $_FILES["file"]["name"]));
  if ((($_FILES["file"]["type"] == "image/gif")
  || ($_FILES["file"]["type"] == "image/jpeg")
  || ($_FILES["file"]["type"] == "image/png")
  || ($_FILES["file"]["type"] == "image/pjpeg"))
  && ($_FILES["file"]["size"] < 200000)
  && in_array($extension, $allowedExts))
    {
    if ($_FILES["file"]["error"] > 0)
      {
      echo "Return Code: " . $_FILES["file"]["error"] . "<br>";
      }
    else
      {
      echo "Upload: " . $_FILES["file"]["name"] . "<br>";
      echo "Type: " . $_FILES["file"]["type"] . "<br>";
      echo "Size: " . ($_FILES["file"]["size"] / 1024) . " kB<br>";
      echo "Temp file: " . $_FILES["file"]["tmp_name"] . "<br>";
  
      if (file_exists("uploads/" . $_FILES["file"]["name"]))
        {
        echo $_FILES["file"]["name"] . " already exists. ";
        }
      else
        {
        move_uploaded_file($_FILES["file"]["tmp_name"],
        "uploads/" . $_FILES["file"]["name"]);
        echo "Stored in: " . "uploads/" . $_FILES["file"]["name"];
        }
      }
    }
  else
    {
    echo "Invalid file";
    }  
} 


The error codes in the $_FILES array indicate that in file that only two files:

<pre>Array (
    [file] => Array (
        [name] => Array (
            [0] => logo.gif
            [1] =>
            [2] =>
            [3] => signs.png
            [4] =>
            [5] =>                  
        )
        [type] => Array (
            [0] => image/gif
            [1] =>
            [2] =>
            [3] => image/png
            [4] =>
            [5] =>
        )
        [tmp_name] => Array (
            [0] => /tmp/phpyIfS3A
            [1] =>
            [2] =>
            [3] => /tmp/phpBDNY6b
            [4] =>
            [5] =>
        )
        [error] => Array (
            [0] => 0
            [1] => 4
            [2] => 4
            [3] => 0
            [4] => 4
            [5] => 4
        )
        [size] => Array (
            [0] => 6258
            [1] => 0
            [2] => 0
            [3] => 91631
            [4] => 0
            [5] => 0
        )
    )
) </pre>

When looping through the files to be processed use is_uploaded_file() on each one in turn and if no file has been uploaded on that pass then use break to end that pass. You might want to consider noting the failure in an error log. Also you might want to consider using [URL=“http://uk1.php.net/manual/en/function.exif-imagetype.php”]exif_imagetype() on each image to check that the extension matches up with what it is as file extensions can’t be 100% relied upon.

Oh, sorry, I forgot that if you set the file input’s name to use square brackets like file[] then $_FILES array has this unintuitive structure like SpacePhoenix presented above so it’s not possible to directly loop through the files using

foreach ($_FILES["file"] as $file)

You’d have to loop through each file property like this:


foreach ($_FILES["file"]["name"] as $file_name) {
  // loop through all file names...
}

foreach ($_FILES["file"]["type"] as $file_type) {
  // loop through all file types...
}
// and so on...

This becomes very clumsy (I don’t know why PHP developers made the $_FILES array like this as it only complicates things…) , so what I do is loop like this:


foreach ($_FILES["file"]["name"] as $index => $file_name) {
  // loop through all file names: file name is available in $file_name and we will grab other
  // file properties directly from $_FILES using $index

  if ($file_name == '') {
    // no file uploaded in this input
    continue;
  }

  // access other file properties like this:
  $type = $_FILES["file"]["type"][$index];
  $tmp_name = $_FILES["file"]["tmp_name"][$index];
  $error = $_FILES["file"]["error"][$index];
  $size = $_FILES["file"]["size"][$index];
  $type = $_FILES["file"]["type"][$index];

  // your code to handle file upload...
  // ...
}

I kind of want to use the is_uploaded_fie() to check even if a file has even been uplo0aded


if (is_uploaded_file($_FILES['file']['tmp_name'])) {
   echo "File ". $_FILES['file']['name'] ." uploaded successfully.\
";
   echo "Displaying contents\
";
   readfile($_FILES['file']['tmp_name']);
} else {
   echo "Possible file upload attack: ";
   echo "filename '". $_FILES['file']['tmp_name'] . "'.";
}

which produces this error?

Warning: is_uploaded_file() expects parameter 1 to be string, array given in /home/fixmy1/public_html/masterasp/providers/thanks.php on line 47
Possible file upload attack: filename ‘Array’
But if look into FILES when I try to upload 1 image, I get this



<pre>Array (     [file] => Array         (             [name] => Array                 (                     [0] => logo.gif                     [1] =>                      [2] =>                      [3] =>                      [4] =>                      [5] =>                  )              [type] => Array                 (                     [0] => image/gif                     [1] =>                      [2] =>                      [3] =>                      [4] =>                      [5] =>                  )              [tmp_name] => Array                 (                     [0] => /tmp/php7EJ4VG                     [1] =>                      [2] =>                      [3] =>                      [4] =>                      [5] =>                  )              [error] => Array                 (                     [0] => 0                     [1] => 4                     [2] => 4                     [3] => 4                     [4] => 4                     [5] => 4                 )              [size] => Array                 (                     [0] => 6258                     [1] => 0                     [2] => 0                     [3] => 0                     [4] => 0                     [5] => 0                 )          )  ) </pre>
 

But I guess if (is_uploaded_file($_FILES[‘file’][‘tmp_name’]))
checks an array, so do I instead do
if (is_uploaded_file($_FILES[‘file’][‘tmp_name’]))
Because I have this in my upload form


<fieldset> <legend>Imaages</legend> <div class="column"> <div><label for='file1'>Image 1:</label><input type='file' name='file[]' id='file1'></div> <div><label for='file2'>Image 2:</label><input type='file' name='file[]' id='file2'></div> <div><label for='file3'>Image 3:</label><input type='file' name='file[]' id='file3'></div> </div><div class="column"> <div><label for='file4'>Image 4:</label><input type='file' name='file[]' id='file4'></div> <div><label for='file5'>Image 5:</label><input type='file' name='file[]' id='file5'></div> <div><label for='file6'>Image 6:</label><input type='file' name='file[]' id='file6'></div> </div> </fieldset>

BTW, how did you print the array in the correct format in this forum?

I copied and pasted the var_dump() output from post #4 into Crimson Editor and just moved each element to a new line.

I then to use this function as a wrapper around var_dump()


function dump($dump_var) {
  echo '<pre>';
  var_dump($dump_var);
  echo '</pre>';
}    

When I need to check the contents of a variable or an array I do it via the above and it comes out better.

I’ve been playing around with the problem and come up with this:


<?php

function dump($dump_var) {
  echo '<pre>';
  var_dump($dump_var);
  echo '</pre>';
}

function get_files($_FILES) {
    $files=$_FILES['image'];
    
    $file_count=count($files);
    $count=0;
    
    while ( $count <> $file_count-1 ) {
        $sorted_files[$count]['name']=$files['name'][$count];
        $sorted_files[$count]['type']=$files['type'][$count];
        $sorted_files[$count]['tmp_name']=$files['tmp_name'][$count];
        $sorted_files[$count]['error']=$files['error'][$count];
        $sorted_files[$count]['size']=$files['size'][$count];
        if (!is_uploaded_file($sorted_files[$count]['tmp_name'])) {
            unset($sorted_files[$count]);
        }
        $count++;
    }
    return $sorted_files;
}

echo '<p>The files array before sorting';
dump($_FILES);
echo '</p>';

$the_files=get_files($_FILES);

echo '<p>The files after sorting';
dump($the_files);
echo '</p>';

?>

After that point you’d have to loop through the output of that doing any checks that you might be doing, eg: file types, extension types, file sizes, etc.

thanks, what is the crinsom editor?

http://www.emeraldeditor.com/

That’s what it is, there are others out there as well.

I’d steer clear of any paid-for ones unless you can justify to yourself the cost of them.

ok ran the code as a test, it printed out the first array, but then got

Fatal error: Maximum execution time of 30 seconds exceeded in /home/fixmy1/public_html/masterasp/providers/thanks.php on line 53

I’m really not too sure what the get_files() is doing as the edrror occurs in the while loop
can you explain to me what the function is doing?

does this forum (sitepoint use that editor?

Can you post the code as it stands atm?

The editor that SitePoint uses for posts is basically the standard editor built into vBulletin but modified to suit.

sure (sorry for taking too long)
I have a form with six file upload things



<input type='file' name='file[]' id='file1'>
<input type='file' name='file[]' id='file2'>
<input type='file' name='file[]' id='file3'>
<input type='file' name='file[]' id='file4'>
<input type='file' name='file[]' id='file5'>
<input type='file' name='file[]' id='file6'>

Then I’m trying to upload the files to the uploads directory using php, so I gather I first have to check if a file has even been uploaded


if (is_uploaded_file($_FILES['file']['tmp_name'])) {
   echo "File ". $_FILES['file']['name'] ." uploaded successfully.\
";
   echo "Displaying contents\
";
   readfile($_FILES['file']['tmp_name']);
} else {
   echo "Possible file upload attack: ";
   echo "filename '". $_FILES['file']['tmp_name'] . "'.";
} 


something like this
Here is the code to upload 1 file



 $allowedExts = array("jpg", "jpeg", "gif", "png");
  $extension = end(explode(".", $_FILES["file"]["name"]));
  if ((($_FILES["file"]["type"] == "image/gif")
  || ($_FILES["file"]["type"] == "image/jpeg")
  || ($_FILES["file"]["type"] == "image/png")
  || ($_FILES["file"]["type"] == "image/pjpeg"))
  && ($_FILES["file"]["size"] < 200000)
  && in_array($extension, $allowedExts))
    {
    if ($_FILES["file"]["error"] > 0)
      {
      echo "Return Code: " . $_FILES["file"]["error"] . "<br>";
      }
    else
      {
      echo "Upload: " . $_FILES["file"]["name"] . "<br>";
      echo "Type: " . $_FILES["file"]["type"] . "<br>";
      echo "Size: " . ($_FILES["file"]["size"] / 1024) . " kB<br>";
      echo "Temp file: " . $_FILES["file"]["tmp_name"] . "<br>";
  
      if (file_exists("uploads/" . $_FILES["file"]["name"]))
        {
        echo $_FILES["file"]["name"] . " already exists. ";
        }
      else
        {
        move_uploaded_file($_FILES["file"]["tmp_name"],
        "uploads/" . $_FILES["file"]["name"]);
        echo "Stored in: " . "uploads/" . $_FILES["file"]["name"];
        }
      }
    }
  else
    {
    echo "Invalid file";
    } 

and i need to modify it to look though the files array to only run when needed.
But using the code you gave me



function dump($dump_var) {
  echo '<pre>';
  var_dump($dump_var);
  echo '</pre>';
}

function get_files($_FILES) {
    $files=$_FILES['image'];
    
    $file_count=count($files);
    $count=0;
    
    while ( $count <> $file_count-1 ) {
        $sorted_files[$count]['name']=$files['name'][$count];
        $sorted_files[$count]['type']=$files['type'][$count];
        $sorted_files[$count]['tmp_name']=$files['tmp_name'][$count];
        $sorted_files[$count]['error']=$files['error'][$count];
        $sorted_files[$count]['size']=$files['size'][$count];
        if (!is_uploaded_file($sorted_files[$count]['tmp_name'])) {
            unset($sorted_files[$count]);
        }
        $count++;
    }
    return $sorted_files;
}

echo '<p>The files array before sorting';
dump($_FILES);
echo '</p>';

$the_files=get_files($_FILES);

echo '<p>The files after sorting';
dump($the_files);
echo '</p>';


produced (source code)



<p>The files array before sorting<pre>array(1) {
  ["file"]=>
  array(5) {
    ["name"]=>
    array(6) {
      [0]=>
      string(8) "logo.gif"
      [1]=>
      string(0) ""
      [2]=>
      string(0) ""
      [3]=>
      string(0) ""
      [4]=>
      string(8) "shop.png"
      [5]=>
      string(0) ""
    }
    ["type"]=>
    array(6) {
      [0]=>
      string(9) "image/gif"
      [1]=>
      string(0) ""
      [2]=>
      string(0) ""
      [3]=>
      string(0) ""
      [4]=>
      string(9) "image/png"
      [5]=>
      string(0) ""
    }
    ["tmp_name"]=>
    array(6) {
      [0]=>
      string(14) "/tmp/phpxTCzY2"
      [1]=>
      string(0) ""
      [2]=>
      string(0) ""
      [3]=>
      string(0) ""
      [4]=>
      string(14) "/tmp/phpT4bvGm"
      [5]=>
      string(0) ""
    }
    ["error"]=>
    array(6) {
      [0]=>
      int(0)
      [1]=>
      int(4)
      [2]=>
      int(4)
      [3]=>
      int(4)
      [4]=>
      int(0)
      [5]=>
      int(4)
    }
    ["size"]=>
    array(6) {
      [0]=>
      int(6258)
      [1]=>
      int(0)
      [2]=>
      int(0)
      [3]=>
      int(0)
      [4]=>
      int(53532)
      [5]=>
      int(0)
    }
  }
}
</pre></p><br />
<b>Fatal error</b>:  Maximum execution time of 30 seconds exceeded in <b>/home/fixmy1/public_html/masterasp/providers/thanks.php</b> on line <b>60</b><br />

Can you show me how I screwed things up?

I gather the function getimagesize() returns false if a non-image is uploaded, so I think this will be handy,
http://www.phpeasystep.com/phptu/25.html

How many files are you trying to upload and what size are they approximately?

It will be an image upload thing for my site, so I guess I should limit the size at around 200K or so and right now I allow them to upload up to 6 images.

Are you to busy to help? If you are, its ok, but I hope you can point me in the right direction.

Thanks…