6

I have the following $_FILES array past through for processing from a support form

Array
(
    [file] => Array
        (
            [name] => Array
                (
                    [0] => Test.jpg
                    [1] => Test.doc
                    [2] => Test.php
                    [3] => 
                )

            [type] => Array
                (
                    [0] => image/jpeg
                    [1] => image/jpeg
                    [2] => image/jpeg
                    [3] => 
                )

            [tmp_name] => Array
                (
                    [0] => /tmp/phpCO0vSD
                    [1] => /tmp/phpEFpp3Q
                    [2] => /tmp/phpwN4Iwc
                    [3] => 
                )

            [error] => Array
                (
                    [0] => 0
                    [1] => 0
                    [2] => 0
                    [3] => 4
                )

            [size] => Array
                (
                    [0] => 1305787
                    [1] => 339773
                    [2] => 480098
                    [3] => 0
                )

        )

)

My main problem is understanding the logic required in order to process the array, check each file is valid (which I already have a list of valid extensions) then rename and store the file appropriately.

The solutions on Google and SO are both rather complex for my simple requirements.

2
  • 1
    They had full solutions that I couldn't get my head around hence the question - thank you for your answer :) Commented Sep 18, 2011 at 22:41
  • the issue you have is not a fundamental trouble, it is just a traversing an array :-S Commented Sep 18, 2011 at 22:42

5 Answers 5

6

Here is how you would traverse your array:

foreach ($_FILES['file']['name'] as $key => $name) {
    echo $name;
    echo $_FILES['file']['type'][$key];
    echo $_FILES['file']['tmp_name'][$key];
}

Having this loop you can do what you want easily.

Sign up to request clarification or add additional context in comments.

Comments

5

I love foreach() so much, I always go with this...

$files = array();
foreach ($_FILES['files']['name'] as $num_key => $dummy) {
    foreach ($_FILES['files'] as $txt_key => $dummy) {
        $files[$num_key][$txt_key] = $_FILES['files'][$txt_key][$num_key];
    }
}

...and then I use foreach($files as $file) again to work with data nicely. :)

Of course that answer from zerkms is faster, but this is general aproach to reorder array logic for any case - you have to walk it twice (x*y).

1 Comment

Thank you! This is exactly what I needed. If you'll be doing any advanced processing with multiple uploaded files, this answer provides a much easier method of doing so. +1
4

Here is a more general solution to seoguru's answer. It works with file input fields whose name contains any level of nested arrays, for example file, file[] (the case for this question), file[english], file[english][], etc.

function rearrangeUploadArray(array $array) {
   if(!is_array(reset($array)))
      return $array;

   $rearranged = [];
   foreach($array as $property => $values)
      foreach($values as $key => $value)
         $rearranged[$key][$property] = $value;

   foreach($rearranged as &$value)
      $value = rearrangeUploadArray($value);

   return $rearranged;
}

I realize that this answer is more complicated than it has to be for this question, but maybe it can be useful for someone sometime. An example use case is a localized upload form, where multiple files can be uploaded for different languages. Then it would make sense to have one file input field for each language, named for example file[english][], file[german][], file[spanish][], etc. rearrangeUploadArray($_FILES['file']) will then return an array on the form

Array
(
    [english] => Array
        (
            [0] => Array
                (
                    [name] => ...
                    [type] => ...
                    [tmp_name] => ...
                    [error] => ...
                    [size] => ...
                )

            [1] => Array
                (
                    [name] => ...
                    [type] => ...
                    [tmp_name] => ...
                    [error] => ...
                    [size] => ...
                )

            [...]
        )
    [german] => Array
        (
            [0] => Array
                (
                    [name] => ...
                    [type] => ...
                    [tmp_name] => ...
                    [error] => ...
                    [size] => ...
                )

            [...]
        )
    [spanish] => Array
        (
            [0] => Array
                (
                    [name] => ...
                    [type] => ...
                    [tmp_name] => ...
                    [error] => ...
                    [size] => ...
                )

            [...]
        )
)

4 Comments

If J. S. Bach were a programmer, he would have done it that way.
Where are the opening and closing brackets for the foreach loops??
@Cavalier I assume you mean braces, not brackets. They are optional :)
@MagnarMyrtveit If you have more than just the single line, are you required to use the braces :) and yes, I meant braces not bracket :D come to think of it, I don't always use the braces when I do a short If statement and I keep it all on a single line. Didn't realize you could do that for a foreach statement.
2

Another variant of recursive reordering based on clamcrusher's solution from here

function getFixedFilesArray() {
    $walker = function ($arr, $fileInfokey, callable $walker) {
        $ret = array();
        foreach ($arr as $k => $v) {
            if (is_array($v)) {
                $ret[$k] = $walker($v, $fileInfokey, $walker);
            } else {
                $ret[$k][$fileInfokey] = $v;
            }
        }
        return $ret;
    };

    $files = array();
    foreach ($_FILES as $name => $values) {
        // init for array_merge
        if (!isset($files[$name])) {
            $files[$name] = array();
        }
        if (!is_array($values['error'])) {
            // normal syntax
            $files[$name] = $values;
        } else {
            // html array feature
            foreach ($values as $fileInfoKey => $subArray) {
                $files[$name] = array_replace_recursive($files[$name], $walker($subArray, $fileInfoKey, $walker));
            }
        }
    }

    return $files;
}

The main difference from the original solution is that I replaced array_merge_recursive with array_replace_recursive so that indexed arrays in a tree will not produce invalid result (array_merge_recursive for indexed arrays adds new indexes instead of merging with existing indexes). I've tested this on several quite difficult situations and it worked as expected

Comments

0

This would work - tested!

if( !empty($_FILES['SOME_INPUT_NAME'] ) {
    $multimgs   = $_FILES['SOME_INPUT_NAME'];
    $imgs_arr   = array();

    // first build into working array
    foreach($multimgs as $key => $value) {
        foreach($pimgs[$key] as $subkey => $subvalue) {
            $imgs_arr[$subkey][$key] = $subvalue;
        }
    }
}

Then you can loop through $imgs_arr - images array. those would be in a normal,
FILE structure which you can use to upload etc.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.