欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

PHP 文件上传

shiping1 的头像
通过 PHP,可以把文件上传到服务器。

创建一个文件上传表单

允许用户从表单上传文件是非常有用的。

请看下面这个供上传文件的 HTML 表单:

<html>
<body>

<form action="upload_file.php" method="post"
enctype="multipart/form-data">
<label for="file">Filename:</label>
<input type="file" name="file" id="file" /> 
<br />
<input type="submit" name="submit" value="Submit" />
</form>

</body>
</html>

请留意如下有关此表单的信息:

<form> 标签的 enctype 属性规定了在提交表单时要使用哪种内容类型。在表单需要二进制数据时,比如文件内容,请使用 "multipart/form-data"。

<input> 标签的 type="file" 属性规定了应该把输入作为文件来处理。举例来说,当在浏览器中预览时,会看到输入框旁边有一个浏览按钮。

注释:允许用户上传文件是一个巨大的安全风险。请仅仅允许可信的用户执行文件上传操作。

创建上传脚本

"upload_file.php" 文件含有供上传文件的代码:

<?php
if ($_FILES["file"]["error"] > 0)
  {
  echo "Error: " . $_FILES["file"]["error"] . "<br />";
  }
else
  {
  echo "Upload: " . $_FILES["file"]["name"] . "<br />";
  echo "Type: " . $_FILES["file"]["type"] . "<br />";
  echo "Size: " . ($_FILES["file"]["size"] / 1024) . " Kb<br />";
  echo "Stored in: " . $_FILES["file"]["tmp_name"];
  }
?>

通过使用 PHP 的全局数组 $_FILES,你可以从客户计算机向远程服务器上传文件。

第一个参数是表单的 input name,第二个下标可以是 "name", "type", "size", "tmp_name" 或 "error"。就像这样:

  • $_FILES["file"]["name"] - 被上传文件的名称
  • $_FILES["file"]["type"] - 被上传文件的类型
  • $_FILES["file"]["size"] - 被上传文件的大小,以字节计
  • $_FILES["file"]["tmp_name"] - 存储在服务器的文件的临时副本的名称
  • $_FILES["file"]["error"] - 由文件上传导致的错误代码

这是一种非常简单文件上传方式。基于安全方面的考虑,您应当增加有关什么用户有权上传文件的限制。

上传限制

在这个脚本中,我们增加了对文件上传的限制。用户只能上传 .gif 或 .jpeg 文件,文件大小必须小于 20 kb:

<?php

if ((($_FILES["file"]["type"] == "image/gif")
|| ($_FILES["file"]["type"] == "image/jpeg")
|| ($_FILES["file"]["type"] == "image/pjpeg"))
&& ($_FILES["file"]["size"] < 20000))
  {
  if ($_FILES["file"]["error"] > 0)
    {
    echo "Error: " . $_FILES["file"]["error"] . "<br />";
    }
  else
    {
    echo "Upload: " . $_FILES["file"]["name"] . "<br />";
    echo "Type: " . $_FILES["file"]["type"] . "<br />";
    echo "Size: " . ($_FILES["file"]["size"] / 1024) . " Kb<br />";
    echo "Stored in: " . $_FILES["file"]["tmp_name"];
    }
  }
else
  {
  echo "Invalid file";
  }

?>

注释:对于 IE,识别 jpg 文件的类型必须是 pjpeg,对于 FireFox,必须是 jpeg。

保存被上传的文件

上面的例子在服务器的 PHP 临时文件夹创建了一个被上传文件的临时副本。

这个临时的复制文件会在脚本结束时消失。要保存被上传的文件,我们需要把它拷贝到另外的位置:

<?php
if ((($_FILES["file"]["type"] == "image/gif")
|| ($_FILES["file"]["type"] == "image/jpeg")
|| ($_FILES["file"]["type"] == "image/pjpeg"))
&& ($_FILES["file"]["size"] < 20000))
  {
  if ($_FILES["file"]["error"] > 0)
    {
    echo "Return Code: " . $_FILES["file"]["error"] . "<br />";
    }
  else
    {
    echo "Upload: " . $_FILES["file"]["name"] . "<br />";
    echo "Type: " . $_FILES["file"]["type"] . "<br />";
    echo "Size: " . ($_FILES["file"]["size"] / 1024) . " Kb<br />";
    echo "Temp file: " . $_FILES["file"]["tmp_name"] . "<br />";

    if (file_exists("upload/" . $_FILES["file"]["name"]))
      {
      echo $_FILES["file"]["name"] . " already exists. ";
      }
    else
      {
      move_uploaded_file($_FILES["file"]["tmp_name"],
      "upload/" . $_FILES["file"]["name"]);
      echo "Stored in: " . "upload/" . $_FILES["file"]["name"];
      }
    }
  }
else
  {
  echo "Invalid file";
  }
?>

上面的脚本检测了是否已存在此文件,如果不存在,则把文件拷贝到指定的文件夹。

注释:这个例子把文件保存到了名为 "upload" 的新文件夹。


来自  http://www.w3school.com.cn/php/php_file_upload.asp

众所周知,文件上传在一些网站应用中是必不可少的一部分。比如个人博客上传个性头像,一些论坛分享好的学习资料等,这就涉及到使用表单处理文件上传的知识,在php中我们可以使用$_FILES这个全局数组来处理。下面就看看基本的文件上传处理部分。首先要说明的,能够上传文件必定是一个安全隐患,所以在开发这部分功能时,一定要注意网站的安全性。而本文所探讨的只是基本的文件上传部分,关于安全性这方面考虑的较少,希望在日后的高级应用中可以学习的到。

PHP预定义变量这一节我们对一些预定义变量进行了一些大概的学习,其中就有$_FILES这个全局变量,那么现在再来详细的了解关于这个全局量的知识,因为我在处理文件上传时,要使用到它的相关功能。

$_FILES参数详解:
$_FILES["file"]["name"] – 被上传文件的名称
$_FILES["file"]["type"] – 被上传文件的类型
$_FILES["file"]["size"] – 被上传文件的大小,以字节计
$_FILES["file"]["tmp_name"] – 存储在服务器的文件的临时副本的名称
$_FILES["file"]["error"] – 由文件上传导致的错误代码

$_FILES["file"]["error"]中的["error"]值情况:
UPLOAD_ERR_OK
0:没有错误发生,文件上传成功
UPLOAD_ERR_INI_SIZE
1:上传的文件超过了 php.ini中upload_max_filesize(默认情况为2M) 选项限制的值
UPLOAD_ERR_FORM_SIZE
2:上传文件的大小超过了 HTML表单中MAX_FILE_SIZE选项指定的值
UPLOAD_ERR_PARTIAL
3:文件只有部分被上传
UPLOAD_ERR_NO_FILE
4:没有文件被上传
5:传文件大小为0
下面我们就来看看最基本的文件上传:

<html>
<body>
<form action=”upload-file.php” method=”post”
enctype=”multipart/form-data”>
<label for=”file”>文件名:</label>
<input type=”file” name=”file” id=”file” />
<br />
<input type=”submit” name=”submit” value=”提交” />
</form>
</body>
</html>

这个HTML页面如下图:

upload-file

upload-file.php代码如下:

<?php
if ($_FILES["file"]["error"] > 0)
  {
  echo “错误: ” . $_FILES["file"]["error"] . “<br />”;
  }
else
  {
  echo “文件名: ” . $_FILES["file"]["name"] . “<br />”;
  echo “类型: ” . $_FILES["file"]["type"] . “<br />”;
  echo “大小: ” . ($_FILES["file"]["size"] / 1024) . ” Kb<br />”;
  echo “存储位置: ” . $_FILES["file"]["tmp_name"];
  }
?>

我们随便上传一个word文件,看看处理结果如何:

文件名: css.doc
类型: application/msword
大小: 81.5 Kb
存储位置: C:\WINDOWS\temp\php7D.tmp

可以看到,这个文件被保存到C:\WINDOWS\temp\临时目录下,你可能想去看看在这个目录是否存在这个文件,但结果是:没有!为什么呢?因为php在执行完这个脚本后,把它生成的文件又删除了,所以在上传之后还要进一步处理。另外还随便提一下,在windows下,php所生成的临时文件如php7D.tmp是有规律的,也就是说在下一次通过表单上传的文件应该像这样:php7E.tmp
为了保存我们上传的文件,要使用move_uploaded_file函数。在你的upload-file.php文件同目录创建一个upload文件夹。下面再来看看上面那个示例:

<?php
if ($_FILES["file"]["error"] > 0)
  {
  echo “错误: ” . $_FILES["file"]["error"] . “<br />”;
  }
else
  {
  echo “文件名: ” . $_FILES["file"]["name"] . “<br />”;
  echo “类型: ” . $_FILES["file"]["type"] . “<br />”;
  echo “大小: ” . ($_FILES["file"]["size"] / 1024) . ” Kb<br />”; 
  }
 if (file_exists(”upload/” . $_FILES["file"]["name"]))
    {
      echo $_FILES["file"]["name"] . ” 文件已经存在. “;
    }
else
    {
      move_uploaded_file($_FILES["file"]["tmp_name"],
      “upload/” . $_FILES["file"]["name"]);
      echo “文件已经被存储到: ” . “upload/” . $_FILES["file"]["name"];
    }

 

?>

再来看看结果:

文件名: css.doc
类型: application/msword
大小: 81.5 Kb
文件已经被存储到: upload/css.doc

经过这一步的处理,在我们所指定的地方(upload)就可以得到我们上传的文件。到这里,最基本的文件上传就结束了。还说一下,我们在上传的时候一定要考虑文件的类型,要考虑文件的大小等。关于这些方面随着学习的深入再来介绍吧

来自 http://scoke.blog.51cto.com/769125/493962



$_FILES

$HTTP_POST_FILES [已弃用]

$_FILES -- $HTTP_POST_FILES [已弃用] — HTTP 文件上传变量

说明 ¶

通过 HTTP POST 方式上传到当前脚本的项目的数组

$HTTP_POST_FILES 包含相同的信息,但它不是一个超全局变量。 (注意 $HTTP_POST_FILES 和 $_FILES 是不同的变量,PHP 处理它们的方式不同)

更新日志 ¶

版本说明
4.1.0引入 $_FILES,弃用 $HTTP_POST_FILES

注释 ¶

Note:

“Superglobal”也称为自动化的全局变量。这就表示其在脚本的所有作用域中都是可用的。不需要在函数或方法中用 global $variable; 来访问它。

参见 ¶

add a note add a note

User Contributed Notes 26 notes

scohen987 at gmail dot com ¶
1 year ago
see http://php.net/manual/en/features.file-upload.post-method.php for documentation of the $_FILES array, which is what I came to this page for in the first place.
sergio_ag at terra dot com dot br ¶
3 years ago
A nice trick to reorder the $_FILES array when you use a input name as array is: 

<?php 
function diverse_array($vector) { 
    
$result = array(); 
    foreach(
$vector as $key1 => $value1
        foreach(
$value1 as $key2 => $value2
            
$result[$key2][$key1] = $value2
    return 
$result

?> 

will transform this: 

array(1) { 
    ["upload"]=>array(2) { 
        ["name"]=>array(2) { 
            [0]=>string(9)"file0.txt" 
            [1]=>string(9)"file1.txt" 
        } 
        ["type"]=>array(2) { 
            [0]=>string(10)"text/plain" 
            [1]=>string(10)"text/html" 
        } 
    } 


into: 

array(1) { 
    ["upload"]=>array(2) { 
        [0]=>array(2) { 
            ["name"]=>string(9)"file0.txt" 
            ["type"]=>string(10)"text/plain" 
        }, 
        [1]=>array(2) { 
            ["name"]=>string(9)"file1.txt" 
            ["type"]=>string(10)"text/html" 
        } 
    } 


just do: 

<?php $upload diverse_array($_FILES["upload"]); ?>
brian at diamondsea dot com ¶
1 year ago
If you are looking for the $_FILES['error'] code explanations, be sure to read:

Handling File Uploads - Error Messages Explained
http://www.php.net/manual/en/features.file-upload.errors.php
calurion at gmail dot com ¶
6 years ago
For some reason when I tried to check if $_FILES['myVarName'] was empty() or !isset() or array_key_exists(), it always came back that the file was indeed in the superglobal, even when nothing was uploaded.

I wonder if this is a result of enctype="multipart/form-data".

Anyways, I solved my issue by checking to make sure that $_FILES['myVarName']['size'] > 0
dewi at dewimorgan dot com ¶
6 years ago
The format of this array is (assuming your form has two input type=file fields named "file1", "file2", etc):

Array
(
    [file1] => Array
        (
            [name] => MyFile.txt (comes from the browser, so treat as tainted)
            [type] => text/plain  (not sure where it gets this from - assume the browser, so treat as tainted)
            [tmp_name] => /tmp/php/php1h4j1o (could be anywhere on your system, depending on your config settings, but the user has no control, so this isn't tainted)
            [error] => UPLOAD_ERR_OK  (= 0)
            [size] => 123   (the size in bytes)
        )

    [file2] => Array
        (
            [name] => MyFile.jpg
            [type] => image/jpeg
            [tmp_name] => /tmp/php/php6hst32
            [error] => UPLOAD_ERR_OK
            [size] => 98174
        )
)

Last I checked (a while ago now admittedly), if you use array parameters in your forms (that is, form names ending in square brackets, like several file fields called "download[file1]", "download[file2]" etc), then the array format becomes... interesting.

Array
(
    [download] => Array
        (
            [name] => Array
                (
                    [file1] => MyFile.txt
                    [file2] => MyFile.jpg
                )

            [type] => Array
                (
                    [file1] => text/plain
                    [file2] => image/jpeg
                )

            [tmp_name] => Array
                (
                    [file1] => /tmp/php/php1h4j1o
                    [file2] => /tmp/php/php6hst32
                )

            [error] => Array
                (
                    [file1] => UPLOAD_ERR_OK
                    [file2] => UPLOAD_ERR_OK
                )

            [size] => Array
                (
                    [file1] => 123
                    [file2] => 98174
                )
        )
)

So you'd need to access the error param of file1 as, eg $_Files['download']['error']['file1']
andrewpunch at bigfoot dot com ¶
7 years ago
If $_FILES is empty, even when uploading, try adding enctype="multipart/form-data" to the form tag and make sure you have file uploads turned on.
sparticvs at popebp dot com ¶
3 years ago
A note of security: Don't ever trust $_FILES["image"]["type"]. It takes whatever is sent from the browser, so don't trust this for the image type.  I recommend using finfo_open (http://www.php.net/manual/en/function.finfo-open.php) to verify the MIME type of a file. It will parse the MAGIC in the file and return it's type...this can be trusted (you can also use the "file" program on Unix, but I would refrain from ever making a System call with your PHP code...that's just asking for problems).
BigShark666 at gmail dot com ¶
4 years ago
Nontypicall array comes in php after the submission.I wrote a small function to restate it to the familiar look.
<?php
function multiple(array $_files$top TRUE)
{
    
$files = array();
    foreach(
$_files as $name=>$file){
        if(
$top$sub_name $file['name'];
        else    
$sub_name $name;
        
        if(
is_array($sub_name)){
            foreach(
array_keys($sub_name) as $key){
                
$files[$name][$key] = array(
                    
'name'     => $file['name'][$key],
                    
'type'     => $file['type'][$key],
                    
'tmp_name' => $file['tmp_name'][$key],
                    
'error'    => $file['error'][$key],
                    
'size'     => $file['size'][$key],
                );
                
$files[$name] = multiple($files[$name], FALSE);
            }
        }else{
            
$files[$name] = $file;
        }
    }
    return 
$files;
}


print_r($_FILES);
/*
Array
(
    [image] => Array
        (
            [name] => Array
                (
                    [0] => 400.png
                )
            [type] => Array
                (
                    [0] => image/png
                )
            [tmp_name] => Array
                (
                    [0] => /tmp/php5Wx0aJ
                )
            [error] => Array
                (
                    [0] => 0
                )
            [size] => Array
                (
                    [0] => 15726
                )
        )
)
*/

$files multiple($_FILES);
print_r($files);
/*
Array
(
    [image] => Array
        (
            [0] => Array
                (
                    [name] => 400.png
                    [type] => image/png
                    [tmp_name] => /tmp/php5Wx0aJ
                    [error] => 0
                    [size] => 15726
                )
        )
)
*/

?>
John ¶
5 years ago
In the past you could unconditionally call $_FILES['profile_pic'] without ever having to worry about PHP spitting an "Undefined index: profile_pic" error (so long as the page posting had a file input on it (e.g. <input type="file" name="profile_pic" />)). This was the case regardless of whether or not the end user actually uploaded a file. These days, with so many people browsing the web via iPads, you have to explicitly check to see if the input isset($_FILES['profile_pic']) before calling into it, else you'll get the aforementioned error message. This is because iOS devices running Safari disable file inputs thereby causing them to be treated as if they don't exist. Time to update your scripts!

-john
tjbp ¶
3 years ago
For quick debugging (eg. var_dump($_FILES);), these are the values of the error constants. Obviously don't use these for comparison in real code.

UPLOAD_ERR_OK: 0
UPLOAD_ERR_INI_SIZE: 1
UPLOAD_ERR_FORM_SIZE: 2
UPLOAD_ERR_NO_TMP_DIR: 6
UPLOAD_ERR_CANT_WRITE: 7
UPLOAD_ERR_EXTENSION: 8
UPLOAD_ERR_PARTIAL: 3
unca dot alby at gmail dot com ¶
4 years ago
In checking the error code, you probably ought to check for code 4.  I believe Code 4 means no file was uploaded, and there are many instances where that's perfectly OK.

Such as when you have a form with multiple data items, including file and image uploads, plus whatever else.  The user might not be adding a new upload for whatever reason, such as there may already be a file in the system from an earlier update, and the user is satisfied with that.
kbolyshev at gmail dot com ¶
4 years ago
For situation download[file1], download[file2], ..., download[fileN], try it:

<?php

/**
*
* @param array     $arrayForFill
* @param string    $currentKey
* @param mixed     $currentMixedValue
* @param string    $fileDescriptionParam (name, type, tmp_name, error или size)
* @return void
*/

function rRestructuringFilesArray(&$arrayForFill$currentKey$currentMixedValue,$fileDescriptionParam)
{
    if (
is_array($currentMixedValue)) {
        foreach (
$currentMixedValue as $nameKey => $mixedValue) {
            
rRestructuringFilesArray($arrayForFill[$currentKey],
                                     
$nameKey,
                                     
$mixedValue,
                                     
$fileDescriptionParam);
        }
    } else {
        
$arrayForFill[$currentKey][$fileDescriptionParam] = $currentMixedValue;
    }
}


$arrayForFill = array();
foreach (
$_FILES as $firstNameKey => $arFileDescriptions) {
    foreach (
$arFileDescriptions as $fileDescriptionParam => $mixedValue) {
        
rRestructuringFilesArray($arrayForFill,
                                 
$firstNameKey,
                                 
$_FILES[$firstNameKey][$fileDescriptionParam],
                                 
$fileDescriptionParam);
    }
}

$_FILES $arrayForFill;
?>
Sbastien ¶
4 years ago
If you're uploading multiple files and you name your file inputs "upload[]" the $_FILES array will look different than the var_dump posted below. I figured I'd post what it looks like since it caused me (and still causes me) headaches!

array(1) {
    ["upload"]=>array(5) {
        ["name"]=>array(3) {
            [0]=>string(9)"file0.txt"
            [1]=>string(9)"file1.txt"
            [2]=>string(9)"file2.txt"
        }
        ["type"]=>array(3) {
            [0]=>string(10)"text/plain"
            [1]=>string(10)"text/plain"
            [2]=>string(10)"text/plain"
        }
        ["tmp_name"]=>array(3) {
            [0]=>string(14)"/tmp/blablabla"
            [1]=>string(14)"/tmp/phpyzZxta"
            [2]=>string(14)"/tmp/phpn3nopO"
        }
        ["error"]=>array(3) {
            [0]=>int(0)
            [1]=>int(0)
            [2]=>int(0)
        }
        ["size"]=>array(3) {
            [0]=>int(0)
            [1]=>int(0)
            [2]=>int(0)
        }
    }
}

(I thought the array would have looked like upload[index][name] which is not the case.)
Jack Sleight ¶
3 months ago
I've written this function to restructure deeply nested $_FILES arrays, so that the parameters for each file are grouped together.

function restructure_files(array $input)
{
    $output = [];
    foreach ($input as $name => $array) {
        foreach ($array as $field => $value) {
            $pointer = &$output[$name];
            if (!is_array($value)) {
                $pointer[$field] = $value;
                continue;
            }
            $stack = [&$pointer];
            $iterator = new \RecursiveIteratorIterator(
                new \RecursiveArrayIterator($value),
                \RecursiveIteratorIterator::SELF_FIRST
            );
            foreach ($iterator as $key => $value) {
                array_splice($stack, $iterator->getDepth() + 1);
                $pointer = &$stack[count($stack) - 1];
                $pointer = &$pointer[$key];
                $stack[] = &$pointer;
                if (!$iterator->hasChildren()) {
                    $pointer[$field] = $value;                                
                }
            }
        }
    }
    return $output;
}

Turns this:

array (size=2)
  'one' => 
    array (size=5)
      'name' => 
        array (size=1)
          'inner' => 
            array (size=2)
              11 => string 'DM4C2738.jpg' (length=12)
              5 => string 'DM4C2760.jpg' (length=12)
      'type' => 
        array (size=1)
          'inner' => 
            array (size=2)
              11 => string 'image/jpeg' (length=10)
              5 => string 'image/jpeg' (length=10)
      'tmp_name' => 
        array (size=1)
          'inner' => 
            array (size=2)
              11 => string '/private/var/tmp/phploOZRb' (length=26)
              5 => string '/private/var/tmp/phpsFkmIh' (length=26)
      'error' => 
        array (size=1)
          'inner' => 
            array (size=2)
              11 => int 0
              5 => int 0
      'size' => 
        array (size=1)
          'inner' => 
            array (size=2)
              11 => int 1031601
              5 => int 674697
  'two' => 
    array (size=5)
      'name' => string '9ncYySC.jpg' (length=11)
      'type' => string 'image/jpeg' (length=10)
      'tmp_name' => string '/private/var/tmp/phpuG99X9' (length=26)
      'error' => int 0
      'size' => int 882422

Into this:

array (size=2)
  'one' => 
    array (size=1)
      'inner' => 
        array (size=2)
          11 => 
            array (size=5)
              'name' => string 'DM4C2738.jpg' (length=12)
              'type' => string 'image/jpeg' (length=10)
              'tmp_name' => string '/private/var/tmp/phploOZRb' (length=26)
              'error' => int 0
              'size' => int 1031601
          5 => 
            array (size=5)
              'name' => string 'DM4C2760.jpg' (length=12)
              'type' => string 'image/jpeg' (length=10)
              'tmp_name' => string '/private/var/tmp/phpsFkmIh' (length=26)
              'error' => int 0
              'size' => int 674697
  'two' => 
    array (size=5)
      'name' => string '9ncYySC.jpg' (length=11)
      'type' => string 'image/jpeg' (length=10)
      'tmp_name' => string '/private/var/tmp/phpuG99X9' (length=26)
      'error' => int 0
      'size' => int 882422
Jmanuel_castillo_exe at yahoo dot com ¶
1 year ago
I spent 3 hours trying to find out why when I upload multiples file $_FILES  return empty, I did noticed it was only when I select files that exceed 3m so I thought it was something related to the MAX_UPLOAD_SIZE that for my surprice came as default as 20m which was very confusing. Later I discovery the problem was in the POST_MAX_SIZE been 3m, so it happen that not only MAX_UPLOAD_SIZE is responsible and that is why I'd like to know there is no error message that shows the cause.
Anonymous ¶
4 years ago
Having url rewrite patterns in .htaccess file which modify your urls can affect $_FILES sometimes. Even though the php page loads and works fine, this variable may not work because of it. Therefore if you rewrite 'www.example.com' to 'example.com', make sure you use the latter one when sending POST to the php page. I'm still not sure why this happens, but its worth noting here so others don't spend time chasing ghosts.
yuriy dot nayda at gmail dot com ¶
3 years ago
THis is an solution to convert Cyrillic and umlaut characters as file name when uplaoding files into needed encoding. Was searching for it but could not find. Thus posting this. Just like this:

$value = mb_convert_encoding($value, "UTF-8");
Anonymous ¶
4 years ago
As mentioned , you should check the error index of the upload.

Example below suggests you have a file field named 'image'.

<?php

        
if($_FILES['image']['error'] == 0){
            
// success - move uploaded file and process stuff here

        
}else{
            
// 'there was an error uploading file' stuff here....    
        
}
?>
Alexandre Teles ¶
3 years ago
You can check error index this way:

<?php

$errorIndex 
$_FILES["file"]["error"];

if (
$errorIndex 0) {
    die(
'We have a error. Try Again.');
}


processFile();

?>
badandyomega at gmail dot com ¶
2 years ago
Others have posted about how the $_FILES array organizes data differently depending on whether the HTML input is a single or multiple type, so it seems to be a common enough problem.  If for some reason you need to mix-and-match the types, or you're not sure which how many files you'll be expecting from a multiple input, this is a very useful way to reorganize the $_FILES array.  Also, unlike some of the earlier posts, the formatting of the new array (i.e. the number of keys and values) is consistent.

<?php
// Reorganize $_FILES array information
$files = Array ();
$i 0;

// Start with all inputs in $_FILES array
foreach ($_FILES as $input)
{
    
$j 0;
    
    foreach (
$input as $property => $value)
    {
        if (
is_array($value))
        {
            
$j count($value); // Number of iterations
            
            
for ($k 0$k $j; ++$k)
            {
                
$files[$i $k][$property] = $value[$k];
            }
        }
        else
        {
            
$j 1;
            
            
$files[$i][$property] = $value;
        }
    }
    
    
$i += $j;
}

?>

The results will look something like this:
$files = Array (
   [0] => Array (
      [name] => '' 
      [type] => ''
      [tmp_name] => ''
      [error] => 0
      [size] => 0 
   )
)
seifert at alesak dot net ¶
3 years ago
I just spent long time debugging strange behavior of one of our application on new webhosting. We have 30 file inputs on one page for upload to server. Problem was that only 20 was actually uploaded.

Now I found there is an option max_file_uploads in php.ini limiting maximum size of $_FILES to 20 by default.

When you have suhosin extension installed it has own option limiting same thing to 25 (suhosin.upload.max_uploads in php.ini)
phazei at gmail dot com ¶
2 years ago
I realize there are a number of posts here for reformating the php $_FILES array, but they don't handle all cases.  This handles the single case, the multiple file case, and even submitting multiple file arrays.  This way no matter what, before ever touching the files array I call this regardless of what it might be:

<?php
    
/**
     * This is to fix the odd files array PHP creates when a file input has a name that's php array:
     * eg: <file name="model[column]" value='file1'> <file name="model[column2][]" value='file2'>
     * becomes:  $_FILES['model']['name'][column] = file1_name.xxx
     *           $_FILES['model']['name'][column2][0] = file2_name.xxx
     *
     * this changes it to:
     *           $files['model'][column]['name'] = file1_name.xxx
     *           $files['model'][column2][0]['name'] = file2_name.xxx
     *
     * This way the file data is grouped together as expected and as it does with a non-array type name attribute
     */
    
static public function multi_file_fix($files null)
    {

        if (
$files == null) {
            
$files = (is_array($_FILES)) ? $_FILES : array();
        }

        
//make there there is a file, and see if the first item is also an array
        
$new_files = array();
        foreach (
$files as $name => $attributes) {
            if (
is_array(reset($attributes))) { //check first item
                
foreach ($attributes as $attribute => $item) { //array file submit, eg name="model[file]"
                    
foreach ($item as $key => $value) {
                        if (
is_array($value)) {
                            foreach (
$value as $key2 => $sub_val) { // multi-array file submit, eg name="model[file][]"
                                
$new_files[$name][$key][$key2][$attribute] = $sub_val;
                            }
                        } else {
                            
$new_files[$name][$key][$attribute] = $value;
                        }
                    }
                }
            } else { 
// regular file submit, eg name="file"
                
$new_files[$name] = $attributes;
            }
        }

        return 
$new_files;
    }


//Usage:

$files multi_file_fix($_FILES);

?>
delete dot this dot and dot dots dot gt at kani dot hu ¶
1 year ago
Here is my version of $_FILES rearrange. Unlike other codes here, this working well on any depth of $_FILES.
<?php
if (!empty($_FILES)) {
    function 
rearrange_files_array(array $array) {
        foreach (
$array as &$value) {
            
$_array = array();
            foreach (
$value as $prop => $propval) {
                if (
is_array($propval)) {
                    
array_walk_recursive($propval, function(&$item$key$value) use($prop) {
                        
$item = array($prop => $item);
                    }, 
$value);
                    
$_array array_replace_recursive($_array$propval);
                } else {
                    
$_array[$prop] = $propval;
                }
            }
            
$value $_array;
        }
        return 
$array;
    }
    echo 
'<pre>'.print_r(rearrange_files_array($_FILES), true).'</pre>';
}

?>
<form method="post" enctype="multipart/form-data" style="clear: both;">
    <h3>upload1</h3>
    <div><label>new0</label><input type="file" name="upload1[new][]" /></div>
    <div><label>new1</label><input type="file" name="upload1[new][]" /></div>
    <div><label>update.id11</label><input type="file" name="upload1[update][id11]" /></div>
    <div><label>update.id12</label><input type="file" name="upload1[update][id12]" /></div>
    <hr />
    <h3>upload2</h3>
    <div><label>new0</label><input type="file" name="upload2[]" /></div>
    <div><label>new1</label><input type="file" name="upload2[]" /></div>
    <div><label>update.id21</label><input type="file" name="upload2[id21]" /></div>
    <div><label>update.id22</label><input type="file" name="upload2[id22]" /></div>
    <hr />
    <div><label>upload3</label><input type="file" name="upload3" /></div>
    <input type="submit" value="go" />
</form>

The output after empty form is posted:
Array
(
    [upload1] => Array
        (
            [new] => Array
                (
                    [0] => Array
                        (
                            [name] => 
                            [type] => 
                            [tmp_name] => 
                            [error] => 4
                            [size] => 0
                        )
                    [1] => Array
                        (
                            [name] => 
                            [type] => 
                            [tmp_name] => 
                            [error] => 4
                            [size] => 0
                        )
                )
            [update] => Array
                (
                    [id11] => Array
                        (
                            [name] => 
                            [type] => 
                            [tmp_name] => 
                            [error] => 4
                            [size] => 0
                        )
                    [id12] => Array
                        (
                            [name] => 
                            [type] => 
                            [tmp_name] => 
                            [error] => 4
                            [size] => 0
                        )
                )
        )
    [upload2] => Array
        (
            [0] => Array
                (
                    [name] => 
                    [type] => 
                    [tmp_name] => 
                    [error] => 4
                    [size] => 0
                )
            [1] => Array
                (
                    [name] => 
                    [type] => 
                    [tmp_name] => 
                    [error] => 4
                    [size] => 0
                )
            [id21] => Array
                (
                    [name] => 
                    [type] => 
                    [tmp_name] => 
                    [error] => 4
                    [size] => 0
                )
            [id22] => Array
                (
                    [name] => 
                    [type] => 
                    [tmp_name] => 
                    [error] => 4
                    [size] => 0
                )
        )
    [upload3] => Array
        (
            [name] => 
            [type] => 
            [tmp_name] => 
            [error] => 4
            [size] => 0
        )
)
Sam ¶
6 years ago
This is REQUIRED by the xhtml specs.
mwgamera at gmail dot com ¶
6 years ago
To determine whether upload was successful you should check for error being UPLOAD_ERR_OK instead of checking the file size. When nothing is chosen to be uploaded, the key in $_FILES will still be there, but it should have error equal UPLOAD_ERR_NO_FILE.
kennyp33 at gmail dot com ¶
7 months ago
If you are getting NULL values and want to see what error is being returned you can add ' 2>&1' to the end of your command. On a linux server this will redirect the stderr to stdout (so the string error will be output). This probably saved me a ton of time.
来自 http://php.net/manual/zh/reserved.variables.files.php
普通分类: