it-swarm.com.de

Wie durchlaufen Sie das $ _FILES-Array?

Hier sind die Eingänge, die ich durchlaufen möchte 

Main photo:   <input type="file" name="image[]" />
Side photo 1: <input type="file" name="image[]" />
Side photo 2: <input type="file" name="image[]" />
Side photo 3: <input type="file" name="image[]" />

Ein paar seltsame Dinge passierten, als ich nichts hochgeladen habe, benutze ich die count($_FILES['image']). Ich wiederholte diese Funktion und gab den Wert 5 zurück. In diesem Array sollten sich keine Elemente befinden. Warum gibt es eine zusätzliche Eingabe, wenn ich nur 4 Dateien habe?

Jetzt mit der eigentlichen Schleife selbst probiere ich die foreach-Schleife aus, aber es funktioniert nicht.

foreach($_FILES['image'] as $files){echo $files['name']; }

Nichts kam auf, ich wollte letztendlich alle Bilder durchlaufen, sicherstellen, dass sie das richtige Format und die richtige Größe haben und jedes von ihnen umbenennen. Aber diese einfache foreach () -Schleife zeigt, dass ich irgendwie nicht einmal das $ _FILES-Array durchlaufen kann, und das count () verwirrte mich noch mehr, wenn es besagt, dass das Array 5 Elemente enthält, wenn ich überhaupt nichts hochgeladen habe.

18
Ben

Ihr Beispielformular sollte gut funktionieren. Es ist nur so, dass Sie davon ausgehen, dass die $_FILES-Superglobal-Struktur sich von der tatsächlichen unterscheidet, wenn Sie eine Array-Struktur für die Feldnamen verwenden.

Die Struktur dieses mehrdimensionalen Arrays ist wie folgt:

$_FILES[fieldname] => array(
    [name] => array( /* these arrays are the size you expect */ )
    [type] => array( /* these arrays are the size you expect */ )
    [tmp_name] => array( /* these arrays are the size you expect */ )
    [error] => array( /* these arrays are the size you expect */ )
    [size] => array( /* these arrays are the size you expect */ )
);

count( $_FILES[ "fieldname" ] ) ergibt 5.
Aber das Zählen tieferer Dimensionen führt auch nicht zu dem Ergebnis, das Sie erwarten können. Das Zählen der Felder beispielsweise mit count( $_FILES[ "fieldname" ][ "tmp_name" ] ) führt immer zu der Anzahl der Dateifelder, nicht zu der Anzahl der tatsächlich hochgeladenen Dateien. Sie müssen immer noch die Elemente durchlaufen, um festzustellen, ob für ein bestimmtes Dateifeld etwas hochgeladen wurde.

EDIT
Um durch die Felder zu blättern, würden Sie beispielsweise Folgendes tun:

// !empty( $_FILES ) is an extra safety precaution
// in case the form's enctype="multipart/form-data" attribute is missing
// or in case your form doesn't have any file field elements
if( strtolower( $_SERVER[ 'REQUEST_METHOD' ] ) == 'post' && !empty( $_FILES ) )
{
    foreach( $_FILES[ 'image' ][ 'tmp_name' ] as $index => $tmpName )
    {
        if( !empty( $_FILES[ 'image' ][ 'error' ][ $index ] ) )
        {
            // some error occured with the file in index $index
            // yield an error here
            return false; // return false also immediately perhaps??
        }

        /*
            edit: the following is not necessary actually as it is now 
            defined in the foreach statement ($index => $tmpName)

            // extract the temporary location
            $tmpName = $_FILES[ 'image' ][ 'tmp_name' ][ $index ];
        */

        // check whether it's not empty, and whether it indeed is an uploaded file
        if( !empty( $tmpName ) && is_uploaded_file( $tmpName ) )
        {
            // the path to the actual uploaded file is in $_FILES[ 'image' ][ 'tmp_name' ][ $index ]
            // do something with it:
            move_uploaded_file( $tmpName, $someDestinationPath ); // move to new location perhaps?
        }
    }
}

Weitere Informationen finden Sie in den Dokumenten .

41
Decent Dabbler

benennen Sie Ihre Felder einfach so um

Main photo:   <input type="file" name="image1" />
Side photo 1: <input type="file" name="image2" />
Side photo 2: <input type="file" name="image3" />
Side photo 3: <input type="file" name="image4" />

und dann können Sie es wie üblich wiederholen:

foreach($_FILES as $file){
  echo $file['name']; 
}
11

Kurze Funktion zum Wiederherstellen von $ _FILES ['files'] mit etwas mehr erwarteter Struktur.

function restructureFilesArray($files)
{
    $output = [];
    foreach ($files as $attrName => $valuesArray) {
        foreach ($valuesArray as $key => $value) {
            $output[$key][$attrName] = $value;
        }
    }
    return $output;
}
7
j4r3k

Ich habe eine Lösung gefunden, die für $ _FILES-Arrays beliebiger Tiefe funktioniert. Als schnelle Erklärung benötigen Sie einen Algorithmus, der dies tut:

For each subtree in the file tree that's more than one item deep:
  For each leaf of the subtree:
    $leaf[a][b][c] ... [y][z] -> $result[z][a][b][c]  ... [y]

Hier ist ein Code, der tatsächlich funktioniert. 

function sane_file_array($files) {
  $result = array();
  $name = array();
  $type = array();
  $tmp_name = array();
  $error = array();
  $size = array();
  foreach($files as $field => $data) {
    foreach($data as $key => $val) {
      $result[$field] = array();
      if(!is_array($val)) {
        $result[$field] = $data;
      } else {
        $res = array();
        files_flip($res, array(), $data);
        $result[$field] += $res;
      }
    }
  }

  return $result;
}

function array_merge_recursive2($paArray1, $paArray2) {
  if (!is_array($paArray1) or !is_array($paArray2)) { return $paArray2; }
  foreach ($paArray2 AS $sKey2 => $sValue2) {
    $paArray1[$sKey2] = array_merge_recursive2(@$paArray1[$sKey2], $sValue2);
  }
  return $paArray1;
}

function files_flip(&$result, $keys, $value) {
  if(is_array($value)) {
    foreach($value as $k => $v) {
      $newkeys = $keys;
      array_Push($newkeys, $k);
      files_flip($result, $newkeys, $v);
    }
  } else {
    $res = $value;
    // Move the innermost key to the outer spot
    $first = array_shift($keys);
    array_Push($keys, $first);
    foreach(array_reverse($keys) as $k) {
      // You might think we'd say $res[$k] = $res, but $res starts out not as an array
      $res = array($k => $res);     
    }

    $result = array_merge_recursive2($result, $res);
  }
}

Rufen Sie einfach sane_files_array für $ _FILES auf, und Sie sollten gut damit umgehen können, unabhängig davon, wie tief das $ _FILES-Array ist. Dies sollte wirklich Teil der Sprache selbst sein, da die Formatierung des $ _FILES-Arrays absolut lächerlich ist.

3
Lendrick

Könnte sein:

Main photo:   <input type="file" name="image1" />
Side photo 1: <input type="file" name="image2" />
Side photo 2: <input type="file" name="image3" />
Side photo 3: <input type="file" name="image4" />

$i=1;
while (isset($_FILES['image'.$i])) {
    print_r($_FILES['image'.$i]);
    $i++;
}

Wenn Sie bestimmte Dateifelder durchlaufen müssen.

2
woodgate

Die Entscheidung von PHP im Umgang mit $ _FILES kostet viel Entwicklerzeit. Basierend auf der Antwort von @ Lendrick, folgt hier ein ähnlicher OO -Ansatz.

/**
* @brief get the POSTed files in a more usable format
    Works on the following methods:
        <form method="post" action="/" name="" enctype="multipart/form-data">
        <input type="file" name="photo1" />
        <input type="file" name="photo2[]" />
        <input type="file" name="photo2[]" />
        <input type="file" name="photo3[]" multiple />
* @return   Array
* @todo
* @see  http://stackoverflow.com/questions/5444827/how-do-you-loop-through-files-array
*/
public static function GetPostedFiles()
{
    /* group the information together like this example
    Array
    (
        [attachments] => Array
        (
            [0] => Array
            (
                [name] => car.jpg
                [type] => image/jpeg
                [tmp_name] => /tmp/phpe1fdEB
                [error] => 0
                [size] => 2345276
            )
        )
        [jimmy] => Array
        (
            [0] => Array
            (
                [name] => 1.jpg
                [type] => image/jpeg
                [tmp_name] => /tmp/phpx1HXrr
                [error] => 0
                [size] => 221041
            )
            [1] => Array
            (
                [name] => 2 ' .jpg
                [type] => image/jpeg
                [tmp_name] => /tmp/phpQ1clPh
                [error] => 0
                [size] => 47634
            )
        )
    )
    */

    $Result = array();
    $Name = array();
    $Type = array();
    $TmpName = array();
    $Error = array();
    $Size = array();
    foreach($_FILES as $Field => $Data)
    {
        foreach($Data as $Key => $Val)
        {
            $Result[$Field] = array();
            if(!is_array($Val))
                $Result[$Field] = $Data;
            else
            {
                $Res = array();
                self::GPF_FilesFlip($Res, array(), $Data);
                $Result[$Field] += $Res;
            }
        }
    }

    return $Result;
}

private static function GPF_ArrayMergeRecursive($PaArray1, $PaArray2)
{
    // helper method for GetPostedFiles
    if (!is_array($PaArray1) or !is_array($PaArray2))
        return $PaArray2;
    foreach ($PaArray2 AS $SKey2 => $SValue2)
        $PaArray1[$SKey2] = self::GPF_ArrayMergeRecursive(@$PaArray1[$SKey2], $SValue2);
    return $PaArray1;
}

private static function GPF_FilesFlip(&$Result, $Keys, $Value)
{
    // helper method for GetPostedFiles
    if(is_array($Value))
    {
        foreach($Value as $K => $V)
        {
            $NewKeys = $Keys;
            array_Push($NewKeys, $K);
            self::GPF_FilesFlip($Result, $NewKeys, $V);
        }
    }
    else
    {
        $Res = $Value;
        // move the innermost key to the outer spot
        $First = array_shift($Keys);
        array_Push($Keys, $First);
        foreach(array_reverse($Keys) as $K)
            $Res = array($K => $Res); // you might think we'd say $Res[$K] = $Res, but $Res starts out not as an array
        $Result = self::GPF_ArrayMergeRecursive($Result, $Res);
    }
}
0
carrucha

Ich habe seit fast einer Woche mit diesem Dilemma zu kämpfen! Nichts, was ich im Internet gefunden habe, könnte mir helfen. Ich wusste irgendwie, was zu tun ist, aber ich konnte nicht herausfinden, wie ich das $ _FILES-Array richtig durchlaufen sollte - bis jetzt, als ich den bearbeiteten Beitrag der akzeptierten Antwort las.

Ich habe jedoch einige Änderungen am Skript vorgenommen, da es für mich nicht richtig funktioniert hat. Ich wollte herausfinden können, ob überhaupt eine Datei ausgewählt wurde, also habe ich die Zeile geändert "If (! Empty ($ _FILES ['image'] ['error'] [$ index]))" to "if (! empty ($ _FILES ['image'] ['size'] [$ index]))" Und dann anstelle von "false", füge ich stattdessen die Größe in eine Variable ein : "$ Size = $ _FILES ['upload'] ['size'] [$ index];"

Auf diese Weise konnte ich überprüfen, ob die Variable $ Size größer als Null war. Wenn dies der Fall war, wurde eine Datei ausgewählt und ich konnte mit dem Zählen der Anzahl der Dateien fortfahren und den eigentlichen Upload durchführen. Ich habe kein "unnötiges" Skript nach "return false;" in der akzeptierten Antwort verwendet. Hoffe das hilft jemandem.

: P/MacD

0
MacDknife