22

ループしたい入力は次のとおりです

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[]" />

いくつかの奇妙なことが起こりました。何もアップロードしなかったときに count($_FILES['image']). 最初に 4 つのファイルしかないのに、余分な入力が 1 つあるのはなぜですか?

実際にループ自体を使用して、 foreach ループを使用しようとしましたが、機能しません。

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

私が最終的にやりたかったことは、すべての画像をループして、正しい形式、サイズであることを確認し、それぞれの名前を変更することです。しかし、この単純な foreach() ループは、どういうわけか $_FILES 配列をループすることさえできないことを示しており、count() は、何もアップロードしていないのに配列に 5 つの要素があると言うと、さらに混乱します。

4

10 に答える 10

44

サンプルフォームは正常に機能するはずです。$_FILESフィールド名に配列構造を使用する場合、スーパーグローバルの構造が実際とは異なると予想しているだけです。

この多次元配列の構造は次のとおりです。

$_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" ] )、 が得られ5ます。
しかし、より深い次元を数えても、期待する結果は得られません。count( $_FILES[ "fieldname" ][ "tmp_name" ] )たとえば、フィールドをカウントすると、実際にアップロードされたファイルの数ではなく、常にファイル フィールドの数になります。特定のファイル フィールドに対して何かがアップロードされているかどうかを判断するには、要素をループ処理する必要があります。

編集
したがって、フィールドをループするには、次のようにします。

// !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?
        }
    }
}

詳細については、ドキュメントを参照してください。

于 2011-03-26T20:51:56.547 に答える
12

この方法でフィールドの名前を変更するだけです

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" />

そして、通常の方法でそれを繰り返すことができます:

foreach($_FILES as $file){
  echo $file['name']; 
}
于 2011-03-26T19:43:16.453 に答える
11

$_FILES['files'] をより期待される構造に再構築する短い関数。

function restructureFilesArray($files)
{
    $output = [];
    foreach ($files as $attrName => $valuesArray) {
        foreach ($valuesArray as $key => $value) {
            $output[$key][$attrName] = $value;
        }
    }
    return $output;
}
于 2015-09-20T06:52:43.160 に答える
4

任意の深さの $_FILES 配列で機能するソリューションを思いつきました。簡単な説明として、これを行うアルゴリズムが必要なものは次のとおりです。

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]

実際に動作するコードを次に示します。

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);
  }
}

$_FILES で sane_files_array を呼び出すだけで、$_FILES 配列の深さに関係なく、準備が整います。$_FILES 配列の書式設定は絶対にばかげているため、これは実際には言語自体の一部である必要があります。

于 2014-06-24T23:13:53.360 に答える
3

多分:

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++;
}

特定のファイル フィールドをループする必要がある場合。

于 2011-03-26T20:10:17.113 に答える