How can I iterate PHP $_FILES array?

2019-06-27 09:22发布

问题:

This might be stupid question, but PHPs array $_FILES has very odd format, which I have never used before. Can somebody tell me how can I iterate this array in sane way ? I have used to iterate objects or object like arrays, but this format is very odd for me. Is there any way to iterate this array like object array?

( [attachments] => 
    Array ( 
        [name] => Array ( 
            [0] => test1.png 
            [1] => test2.png 
        ) 
        [type] => Array ( 
            [0] => image/png 
            [1] => image/png 
        ) 
        [tmp_name] => Array ( 
            [0] => /tmp/phpmFkEUe 
            [1] => /tmp/phpbLtZRw 
        )
        [error] => Array ( 
            [0] => 0 
            [1] => 0 
        ) 
        [size] => Array ( 
            [0] => 9855 
            [1] => 3002 
        ) 
    ) 
)

回答1:

Wow, that indeed is odd, are you using <input type="file" name="attachments[]" /> in your markup? If you could afford to change those using unique name=, you won't have that odd format...

To directly answer your question, try:

$len = count($_FILES['attachments']['name']);

for($i = 0; $i < $len; $i++) {
   $fileSize = $_FILES['attachments']['size'][$i];
   // change size to whatever key you need - error, tmp_name etc
}


回答2:

I always thought that this structure was nonsense. So whenever I use a multiple input file field, I do this:

$files = array_map('RemapFilesArray'
    (array) $_FILES['attachments']['name'],
    (array) $_FILES['attachments']['type'],
    (array) $_FILES['attachments']['tmp_name'],
    (array) $_FILES['attachments']['error'],
    (array) $_FILES['attachments']['size']
);

function RemapFilesArray($name, $type, $tmp_name, $error, $size)
{
    return array(
        'name' => $name,
        'type' => $type,
        'tmp_name' => $tmp_name,
        'error' => $error,
        'size' => $size,
    );
}

Then you will have an array that you can iterate and each item in it will be an associative array of the same structure that you would get with a normal, single file input. So, if you already have some function for handling those, you can just pass each of these items to it and it will not require any modification.

By the way, the reason to cast all inputs as array is so that this will work even if you forgot to put the [] on the name of your file input (of course you will only get one file in that case, but it's better than breaking).



回答3:

The simplest way is:

$files = $_FILES['attachments']['name'];
$count = 0;
foreach ($files as $file) {
     $file_name = $file;
     $file_type = $_FILES['attachments']['type'][$count];
     $file_size = $_FILES['attachments']['size'][$count];
     ...
     ...

     ++$count;
}


回答4:

This is the only way to iterate $_FILES.

foreach ($_FILES['attachments']['tmp_name'] as $k => $v) {
  echo $_FILES['attachments']['name'][$k];
  echo $_FILES['attachments']['type'][$k];
}


回答5:

this way?

foreach((array)$_FILES["attachments"] as $val) {
   foreach((array)$val["name"] as $name) {
      // $name = "test1.png",...
   }
   foreach((array)$val["type"] as $type) {
      // $type = "imagepng",...
   }   
}


回答6:

I had the same problem while doing multipart forms. Basically I needed to check if theres any file uploads first with 'isset' and then go through every file and do all necessary conditionals.

The fastest way is just to pick one array index element, like ['tmp_name'] and loop that with foreach:

if(isset($_FILES['attachments']) {
   foreach($_FILES['attachments']['tmp_name'] as $key => $value) {
      //do stuff you need/like
   }
}

The main reason to use arrays for multiple file uploads, is that in the end it's much easier to process and iterate. If you use unique names like attachment 1, attachment 2 you run into many problems in more complex situations. I for example, had other upload fields for different attachment categories.

Of course you can do a method, as mentioned before, that fixes the $_FILES array into more clever form, if you find the whole array problematic.



回答7:

I have tried small demonstration , have a look

<html>
<body>
<form enctype="multipart/form-data" method="post">
<input type="file" name="file[]" />
<input type="file" name="file[]" />

<input type="submit" name="submit" />
</form>
<body>
</html>
<?php
if($_SERVER['REQUEST_METHOD']=='POST'){
    foreach ($_FILES as $k=>$v){
   if(is_array($v)){
       foreach ($v as $sk=>$sv){ 
                $arr[$sk][$k]=$sv;
        }
       }
    }
  echo "<pre>";
  print_r($arr);
 }
?>

Output

Array
(
    [name] => Array
        (
            [file] => Array
                (
                    [0] => 4_Milestone text (1).doc
                    [1] => 2x5 ko condolence ad.jpg
                )

        )

    [type] => Array
        (
            [file] => Array
                (
                    [0] => application/msword
                    [1] => image/jpeg
                )

        )

    [tmp_name] => Array
        (
            [file] => Array
                (
                    [0] => C:\xampp\tmp\php15EF.tmp
                    [1] => C:\xampp\tmp\php163E.tmp
                )

        )

    [error] => Array
        (
            [file] => Array
                (
                    [0] => 0
                    [1] => 0
                )

        )

    [size] => Array
        (
            [file] => Array
                (
                    [0] => 20480
                    [1] => 56642
                )

        )

)


回答8:

Here you go: Below function will help you simplify the file upload in a way that you will be able to process it similar to single upload of the file instead of multiple file upload.

HTML: (form.html)

<form method="post" action="post.php" enctype="multipart/form-data">
<input type="file" name="attachment[]" />
<input type="file" name="attachment[]" />
<input type="file" name="attachment[]" />
<input type="submit" value="Upload" />

PHP: (post.php)

<?php
function simplifyMultiFileArray($files = array())
{
    $sFiles = array();
    if(is_array($files) && count($files) > 0)
    {
        foreach($files as $key => $file)
        {
            foreach($file as $index => $attr)
            {
                $sFiles[$index][$key] = $attr;
            }
        }
    }
    return $sFiles;
}

$sFiles = simplifyMultiFileArray($_FILES['attachment']);
echo '<pre>';
print_r($sFiles);
?>


回答9:

There are many ways to clean up the $_FILES array and make it more sensible. Here's my prefered way:

foreach ($_FILES as $fieldname => $keys)
{
    foreach ($keys as $key => $list)
    {
        foreach ($list as $no => $value)
        {
            $files[$fieldname][$no][$key] = $value;
        }
    }
}