如何循环遍历 $_FILES 数组?

发布于 2024-10-27 20:20:11 字数 678 浏览 0 评论 0原文

这是我想要循环的输入

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']),我回显了该函数,并且它返回一个值共 5 个。该数组中不应有任何元素。当我一开始只有 4 个文件时,为什么还要有一个额外的输入?

现在,随着实际的循环本身,我尝试使用 foreach 循环,但它不起作用。

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

什么也没发生,我最终想做的是循环所有图像,确保它们的格式、大小正确,并重命名每个图像。但这个简单的 foreach() 循环表明,不知何故,我什至无法循环遍历 $_FILES 数组,而 count() 当我什至没有上传任何内容时说数组中有 5 个元素时,让我更加困惑。

Here are the inputs I want to loop through

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

A couple weird things happened, when I uploaded nothing I use the count($_FILES['image']), I echoed that function, and it returns a value of 5. There should be no elements in that array. Why is there one extra input when I only have 4 files to begin with?

Now with the actually looping itself, I try using the foreach loop, but it doesn't work.

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

Nothing came up, what I wanted to ultimately do is to loop through all images, make sure they are correct format, size, and rename each of them. But this simple foreach() loop shows that somehow I can't even loop through the $_FILES array and the count() confused me even more when it say that there are 5 elements in the array when I didn't even upload anything.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

您的示例表单应该可以正常工作。只是当使用数组结构作为字段名称时,您期望 $_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?
        }
    }
}

有关详细信息,请参阅

Your example form should work fine. It's just that you are expecting the structure of the $_FILES superglobal to be different than it actually is, when using an array structure for the field names.

The structure of this multidimensional array is as followed then:

$_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 */ )
);

Therefor count( $_FILES[ "fieldname" ] ) will yield 5.
But counting deeper dimensions will also not produce the result you may expect. Counting the fields with count( $_FILES[ "fieldname" ][ "tmp_name" ] ) for instance, will always result in the number of file fields, not in the number of files that have actually been uploaded. You'd still have to loop through the elements to determine whether anything has been uploaded for a particular file field.

EDIT
So, to loop through the fields you would do something like the following:

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

For more information see the docs.

勿忘初心 2024-11-03 20:20:12

将 $_FILES['files'] 重建为更预期的结构的短函数。

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

Short function to rebuild $_FILES['files'] to some more expected structure.

function restructureFilesArray($files)
{
    $output = [];
    foreach ($files as $attrName => $valuesArray) {
        foreach ($valuesArray as $key => $value) {
            $output[$key][$attrName] = $value;
        }
    }
    return $output;
}
橘虞初梦 2024-11-03 20:20: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']; 
}

just rename your fields this way

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

and then you'll be able to iterate it usual way:

foreach($_FILES as $file){
  echo $file['name']; 
}
凉风有信 2024-11-03 20:20:12

我想出了一个适用于任意深度的 $_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 数组的格式绝对是荒谬的。

I came up with a solution that works for $_FILES arrays of arbitrary depth. As a quick explanation, what you need an algorithm that does this:

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]

Here's some code that actually works.

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

Just call sane_files_array on $_FILES and you should be good to go, regardless of how deep the $_FILES array is. This really should be part of the language itself, because the formatting of the $_FILES array is absolutely ridiculous.

空城旧梦 2024-11-03 20:20: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" />

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

如果您必须循环遍历特定的文件字段。

Maybe:

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

If you have to loop through specific file fields.

要走就滚别墨迹 2024-11-03 20:20:12

PHP 选择如何处理 $_FILES 浪费了开发人员的大量时间。基于@Lendrick 的回答,这里有一个类似的面向对象方法。

/**
* @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);
    }
}

PHP's choice of how to handle $_FILES wastes a lot of developer time. Based on @Lendrick's answer, here is a similar OO approach.

/**
* @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);
    }
}
流心雨 2024-11-03 20:20:12

我喜欢@Lendrick 重建数组的尝试。我完全同意 PHP 中原始的 $_FILES 数组纯粹是疯狂的。

替代方案 1

我想出了这个支持多维数组的函数,例如

  /*
   * Return a sane list of uploaded files
   * @author tim-international.net
   */
  function get_uploaded_files() {

    $result = [];
    foreach (preg_split('#&#', http_build_query($_FILES, '&'), -1, PREG_SPLIT_NO_EMPTY) as $pair) {
      list($key, $value) = explode('=', $pair);
      $key = urlencode(preg_replace('#^([^\[]+)\[(name|tmp_name|type|size|error)\](.*)$#', '$1$3[$2]', urldecode($key)));
      $result[] = $key .'='. $value;
    }

    parse_str(implode('&', $result), $result);

    return $result;
  }

的输出示例:

array(1) {
  ["image"]=>
  array(1) {
    [0]=>
    array(5) {
      ["name"]=>
      string(20) "My uploaded file1.png"
      ["type"]=>
      string(9) "image/png"
      ["tmp_name"]=>
      string(27) "C:\Windows\Temp\php6A8E1.tmp"
      ["error"]=>
      int(0)
      ["size"]=>
      int(26570)
    }
    [1]=>
    array(5) {
      ["name"]=>
      string(20) "My uploaded file2.png"
      ["type"]=>
      string(9) "image/png"
      ["tmp_name"]=>
      string(27) "C:\Windows\Temp\php6A8E2.tmp"
      ["error"]=>
      int(0)
      ["size"]=>
      int(26570)
    }
  }
}

使用示例:

$uploaded = get_uploaded_files();
foreach ($uploaded['image'] as $i => $file) {
  move_uploaded_file($uploaded[$i]['tmp_name'], ...);
}

替代 2

另一种变体,它提供了更扁平的效果可以方便的数组是这样的:

  function get_uploaded_files() {

    $result = [];

    foreach (preg_split('#&#', http_build_query($_FILES, '&'), -1, PREG_SPLIT_NO_EMPTY) as $pair) {
      list($key, $value) = explode('=', $pair);
      
      if (preg_match('#^([^\[]+)\[(name|tmp_name|type|size|error)\](.*)$#', urldecode($key), $matches)) {
        $result[$matches[1].$matches[3]][$matches[2]] = urldecode($value);
      }
    }

    return $result;
  }

它返回以下

array(1) {
  ["foo[bar][0]"]=>
    array(5) {
      ["name"]=>
      string(20) "My uploaded file1.png"
      ["type"]=>
      string(9) "image/png"
      ["tmp_name"]=>
      string(27) "C:\Windows\Temp\php6A8E1.tmp"
      ["error"]=>
      int(0)
      ["size"]=>
      int(26570)
    }
    ["foo[bar][1]"]=>
    array(5) {
      ["name"]=>
      string(20) "My uploaded file2.png"
      ["type"]=>
      string(9) "image/png"
      ["tmp_name"]=>
      string(27) "C:\Windows\Temp\php6A8E2.tmp"
      ["error"]=>
      int(0)
      ["size"]=>
      int(26570)
    }
  }
}

使用示例:

foreach (get_uploaded_files() as $field => $file) {
  move_uploaded_file($file['tmp_name'], ...);
}

I like the attempt by @Lendrick to reconstruct the array. I totally agree that the original $_FILES array is purely insane in PHP.

Alternative 1

I came up with this function that supports multidimensional arrays such as <input type="file" name="a[b][c]" />

  /*
   * Return a sane list of uploaded files
   * @author tim-international.net
   */
  function get_uploaded_files() {

    $result = [];
    foreach (preg_split('#&#', http_build_query($_FILES, '&'), -1, PREG_SPLIT_NO_EMPTY) as $pair) {
      list($key, $value) = explode('=', $pair);
      $key = urlencode(preg_replace('#^([^\[]+)\[(name|tmp_name|type|size|error)\](.*)$#', '$1$3[$2]', urldecode($key)));
      $result[] = $key .'='. $value;
    }

    parse_str(implode('&', $result), $result);

    return $result;
  }

Example output for <input type="file" name="image[]" multiple />:

array(1) {
  ["image"]=>
  array(1) {
    [0]=>
    array(5) {
      ["name"]=>
      string(20) "My uploaded file1.png"
      ["type"]=>
      string(9) "image/png"
      ["tmp_name"]=>
      string(27) "C:\Windows\Temp\php6A8E1.tmp"
      ["error"]=>
      int(0)
      ["size"]=>
      int(26570)
    }
    [1]=>
    array(5) {
      ["name"]=>
      string(20) "My uploaded file2.png"
      ["type"]=>
      string(9) "image/png"
      ["tmp_name"]=>
      string(27) "C:\Windows\Temp\php6A8E2.tmp"
      ["error"]=>
      int(0)
      ["size"]=>
      int(26570)
    }
  }
}

Example of use:

$uploaded = get_uploaded_files();
foreach ($uploaded['image'] as $i => $file) {
  move_uploaded_file($uploaded[$i]['tmp_name'], ...);
}

Alternative 2

Another variant which gives a more flattened array that can be handy is this:

  function get_uploaded_files() {

    $result = [];

    foreach (preg_split('#&#', http_build_query($_FILES, '&'), -1, PREG_SPLIT_NO_EMPTY) as $pair) {
      list($key, $value) = explode('=', $pair);
      
      if (preg_match('#^([^\[]+)\[(name|tmp_name|type|size|error)\](.*)$#', urldecode($key), $matches)) {
        $result[$matches[1].$matches[3]][$matches[2]] = urldecode($value);
      }
    }

    return $result;
  }

Which returns the following for <input type="file" name="foo[bar][]" multiple />:

array(1) {
  ["foo[bar][0]"]=>
    array(5) {
      ["name"]=>
      string(20) "My uploaded file1.png"
      ["type"]=>
      string(9) "image/png"
      ["tmp_name"]=>
      string(27) "C:\Windows\Temp\php6A8E1.tmp"
      ["error"]=>
      int(0)
      ["size"]=>
      int(26570)
    }
    ["foo[bar][1]"]=>
    array(5) {
      ["name"]=>
      string(20) "My uploaded file2.png"
      ["type"]=>
      string(9) "image/png"
      ["tmp_name"]=>
      string(27) "C:\Windows\Temp\php6A8E2.tmp"
      ["error"]=>
      int(0)
      ["size"]=>
      int(26570)
    }
  }
}

Example of use:

foreach (get_uploaded_files() as $field => $file) {
  move_uploaded_file($file['tmp_name'], ...);
}
踏雪无痕 2024-11-03 20:20:12

我对这个答案已经很晚了,但我厌倦了一遍又一遍地解决处理 PHP 文件数组的问题,所以我编写了一个 Composer 包,这样我就再也不用这样做了。也许有人在谷歌上搜索会找到我的答案并感到高兴。

安装 tvanc /files-array-organizer

composer require tvanc/files-array-organizer

$_FILES 传递给它,它会返回一个按照您期望的方式构造的数组。

<?php

use tvanc\FilesArrayOrganizer\FilesArrayOrganizer;


require 'vendor/autoload.php';

if ($_FILES) {
    $organizedFiles = FilesArrayOrganizer::organize($_FILES);

    // Now you can foreach over your files
    foreach($organizedFiles['image'] as $file){
        echo $file['name'];
    }
}
?>
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[]" />

I'm way late to the game for this answer but I got tired of solving the problem of dealing with the PHP files array over and over, so I wrote a composer package so I'd never have to again. Maybe someone googling will find my answer and be happy.

Install tvanc/files-array-organizer

composer require tvanc/files-array-organizer

Pass $_FILES to it, and it'll give you back an array that's structured the way you were expecting.

<?php

use tvanc\FilesArrayOrganizer\FilesArrayOrganizer;


require 'vendor/autoload.php';

if ($_FILES) {
    $organizedFiles = FilesArrayOrganizer::organize($_FILES);

    // Now you can foreach over your files
    foreach($organizedFiles['image'] as $file){
        echo $file['name'];
    }
}
?>
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[]" />
一页 2024-11-03 20:20:12

我已经在这个困境中挣扎了快一周了!我在网上找到的任何东西都无法帮助我。我知道该怎么做,但无法弄清楚如何正确循环 $_FILES 数组 - 直到现在我阅读了已接受答案的编辑后的帖子。

不过,我在发布的脚本中做了一些更改,因为它对我来说不能正常工作。我希望能够确定是否选择了文件,所以我更改了该行
"if( !empty( $_FILES[ 'image' ][ 'error' ][ $index ] ) )"

"if( !empty( $_FILES[ 'image' ][ 'size' ][ $index ] ) )"
然后我将大小放入变量中,而不是“return false;”:
“$Size = $_FILES['上传']['大小'][$index];”

这样我可以检查 $Size 变量是否大于零。如果是,则已选择一个文件,我可以继续计算文件数量并进行实际上传。在接受的答案中,我没有在“return false;”之后使用任何“不必要的”脚本。希望这对某人有帮助。

:P
/MacD

I have struggled with this dilemma for almost a week! Nothing I found on the net could help me. I knew sort of what to do, but could not figure out how to loop through the $_FILES array properly - until now when I read the edited post of the accepted answer.

I made some changes though, in the script as posted, as it did not work properly for me. I wanted to be able to determine if a file was selected at all, so I changed the line
"if( !empty( $_FILES[ 'image' ][ 'error' ][ $index ] ) )"
to
"if( !empty( $_FILES[ 'image' ][ 'size' ][ $index ] ) )"
and then instead of "return false;", I put the size into a variable instead:
"$Size = $_FILES[ 'upload' ][ 'size' ][ $index ];"

This way I could check if the $Size variable was larger than zero. If it was, then a file had been selected and I could continue with counting the number of files and do the actual upload. I did not use any of the "unnecessary" script after "return false;", in the accepted answer. Hope this helps someone.

: P
/MacD

朕就是辣么酷 2024-11-03 20:20:12

如果你不能加入他们,那就打败他们。

<?php

class UploadedFile 
{
    public static function walk(&$originalPath, &$path, &$contentType, &$size, &$errorCode)
    {
        if (is_array($originalPath)) {
            foreach ($originalPath as $key => &$value)
                self::walk($value, $path[$key], $contentType[$key], $size[$key], $errorCode[$key]);
        } else {
            $originalPath = [
                'originalPath' => $originalPath,
                'path' => $path,
                'contentType' => $contentType,
                'size' => $size,
                'errorCode' => $errorCode,
            ];
        }
    }

    public static function build()
    {
        // swap second keys
        $rootNode = [];
        foreach ($_FILES as $key => $value) {
            foreach ($value as $key2 => $value2) {
                $rootNode[$key2][$key] = $value2;
            }
        }

        // swap first and last keys
        self::walk($rootNode['name'], $rootNode['tmp_name'], $rootNode['type'], $rootNode['size'], $rootNode['error']);
        
        // remove unused keys
        unset($rootNode['tmp_name']);
        unset($rootNode['type']);
        unset($rootNode['size']);
        unset($rootNode['error']);
        
        return $rootNode['name'];
    }
}
// original
print_r($_FILES);

// restructured
print_r(UploadedFile::build());
// original
Array
(
    [one] => Array
        (
            [name] => ss_break.png
            [type] => image/png
            [tmp_name] => /tmp/phppY8lSV
            [error] => 0
            [size] => 43582
        )

    [multiple] => Array
        (
            [name] => Array
                (
                    [0] => LeleBreeder.png
                )

            [type] => Array
                (
                    [0] => image/png
                )

            [tmp_name] => Array
                (
                    [0] => /tmp/php6GSj1X
                )

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

            [size] => Array
                (
                    [0] => 14284
                )

        )

    [crazy] => Array
        (
            [name] => Array
                (
                    [nested] => Array
                        (
                            [keys] => PlainUbuntu.png
                        )

                )

            [type] => Array
                (
                    [nested] => Array
                        (
                            [keys] => image/png
                        )

                )

            [tmp_name] => Array
                (
                    [nested] => Array
                        (
                            [keys] => /tmp/php4boHkj
                        )

                )

            [error] => Array
                (
                    [nested] => Array
                        (
                            [keys] => 0
                        )

                )

            [size] => Array
                (
                    [nested] => Array
                        (
                            [keys] => 25668
                        )

                )

        )

)

// restructured
Array
(
    [one] => Array
        (
            [originalPath] => ss_break.png
            [path] => /tmp/phppY8lSV
            [contentType] => image/png
            [size] => 43582
            [errorCode] => 0
        )

    [multiple] => Array
        (
            [0] => Array
                (
                    [originalPath] => LeleBreeder.png
                    [path] => /tmp/php6GSj1X
                    [contentType] => image/png
                    [size] => 14284
                    [errorCode] => 0
                )

        )

    [crazy] => Array
        (
            [nested] => Array
                (
                    [keys] => Array
                        (
                            [originalPath] => PlainUbuntu.png
                            [path] => /tmp/php4boHkj
                            [contentType] => image/png
                            [size] => 25668
                            [errorCode] => 0
                        )

                )

        )

)

If you can't join them beat them.

https://gist.github.com/noorwachid/fce70a3a2d96502c2805248c46fc23f9

<?php

class UploadedFile 
{
    public static function walk(&$originalPath, &$path, &$contentType, &$size, &$errorCode)
    {
        if (is_array($originalPath)) {
            foreach ($originalPath as $key => &$value)
                self::walk($value, $path[$key], $contentType[$key], $size[$key], $errorCode[$key]);
        } else {
            $originalPath = [
                'originalPath' => $originalPath,
                'path' => $path,
                'contentType' => $contentType,
                'size' => $size,
                'errorCode' => $errorCode,
            ];
        }
    }

    public static function build()
    {
        // swap second keys
        $rootNode = [];
        foreach ($_FILES as $key => $value) {
            foreach ($value as $key2 => $value2) {
                $rootNode[$key2][$key] = $value2;
            }
        }

        // swap first and last keys
        self::walk($rootNode['name'], $rootNode['tmp_name'], $rootNode['type'], $rootNode['size'], $rootNode['error']);
        
        // remove unused keys
        unset($rootNode['tmp_name']);
        unset($rootNode['type']);
        unset($rootNode['size']);
        unset($rootNode['error']);
        
        return $rootNode['name'];
    }
}
// original
print_r($_FILES);

// restructured
print_r(UploadedFile::build());
// original
Array
(
    [one] => Array
        (
            [name] => ss_break.png
            [type] => image/png
            [tmp_name] => /tmp/phppY8lSV
            [error] => 0
            [size] => 43582
        )

    [multiple] => Array
        (
            [name] => Array
                (
                    [0] => LeleBreeder.png
                )

            [type] => Array
                (
                    [0] => image/png
                )

            [tmp_name] => Array
                (
                    [0] => /tmp/php6GSj1X
                )

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

            [size] => Array
                (
                    [0] => 14284
                )

        )

    [crazy] => Array
        (
            [name] => Array
                (
                    [nested] => Array
                        (
                            [keys] => PlainUbuntu.png
                        )

                )

            [type] => Array
                (
                    [nested] => Array
                        (
                            [keys] => image/png
                        )

                )

            [tmp_name] => Array
                (
                    [nested] => Array
                        (
                            [keys] => /tmp/php4boHkj
                        )

                )

            [error] => Array
                (
                    [nested] => Array
                        (
                            [keys] => 0
                        )

                )

            [size] => Array
                (
                    [nested] => Array
                        (
                            [keys] => 25668
                        )

                )

        )

)

// restructured
Array
(
    [one] => Array
        (
            [originalPath] => ss_break.png
            [path] => /tmp/phppY8lSV
            [contentType] => image/png
            [size] => 43582
            [errorCode] => 0
        )

    [multiple] => Array
        (
            [0] => Array
                (
                    [originalPath] => LeleBreeder.png
                    [path] => /tmp/php6GSj1X
                    [contentType] => image/png
                    [size] => 14284
                    [errorCode] => 0
                )

        )

    [crazy] => Array
        (
            [nested] => Array
                (
                    [keys] => Array
                        (
                            [originalPath] => PlainUbuntu.png
                            [path] => /tmp/php4boHkj
                            [contentType] => image/png
                            [size] => 25668
                            [errorCode] => 0
                        )

                )

        )

)
浊酒尽余欢 2024-11-03 20:20:12

将临时路径与文件名组合起来,将产生一个数组,如下所示:

array(2) {
  ["/tmp/phpAYCvcc"]=> string(10) "file1.jpg"
  ["/tmp/phpCDg79o"]=> string(10) "file2.jpg"
}

代码:

$files = array_combine(
     $_FILES['receipt']['tmp_name'], 
     $_FILES['receipt']['name']
);

foreach ($files as $key => $value) {
    // save your files locally
}

Combining temporary path with the filename which will result an array like:

array(2) {
  ["/tmp/phpAYCvcc"]=> string(10) "file1.jpg"
  ["/tmp/phpCDg79o"]=> string(10) "file2.jpg"
}

The code:

$files = array_combine(
     $_FILES['receipt']['tmp_name'], 
     $_FILES['receipt']['name']
);

foreach ($files as $key => $value) {
    // save your files locally
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文