为什么 $_FILES 在上传文件到 PHP 时是空的?

我在我的 Windows7计算机上安装了 WampServer2。我使用的是 Apache 2.2.11和 PHP 5.2.11。当我试图从表单上上传任何文件时,它似乎是在上传,但在 PHP 中,$_FILES数组是空的。c:\wamp\tmp文件夹中没有文件。我已经配置了 php.ini允许文件上传等。tmp文件夹具有当前用户的读/写权限。我被难住了。

HTML:






Choose a file to upload:

PHP:


233835 次浏览

至于 HTML,您似乎已经正确地设置了该部分。你已经有了 enctype="multipart/form-data",这在表格上非常重要。

至于您的 php.ini设置,有时在系统上存在多个 php.ini文件。确保您编辑的是正确的。我知道你说你已经配置了你的 php.ini文件有文件上传,但你也设置了你的 upload_max_filesizepost_max_size大于你试图上传的文件?所以你应该:

file_uploads = On; sounds like you already did this
post_max_size = 8M; change this higher if needed
upload_max_filesize = 8M; change this higher if needed

您的目录: "c:\wamp\tmp"是否同时具有读写权限?在修改了 php.ini之后,您是否记得重新启动 Apache?


下面是用 PHP 上传文件的检查列表:

  1. 检查 php.ini:
    file_uploads = On
    post_max_size = 100M
    upload_max_filesize = 100M
  • 如果您使用的是共享主机,并且无法访问 php.ini,那么可能需要使用 .htaccess.user.ini
  • 确认一下 您正在编辑正确的 ini 文件- 使用 phpinfo()函数验证您的 设置实际上正在应用。
  • 还有确保你不会 拼写错误的大小-它应该是 100M 没有 100MB
  1. 确保您的 <form>标记具有 enctype="multipart/form-data"属性。没有其他标记将工作,它必须是您的 FORM 标记。再检查一下是不是 拼写正确。仔细检查 multipart/form-data 是否被直引号包围,而不是从 Word 或网站博客中粘贴的智能引号(WordPress 将直引号转换为角引号!).如果页面上有多个窗体,请确保它们都具有此属性。手动键入它们,或者尝试直接手动键入单引号。

  2. 确保没有两个具有相同 name属性的输入文件字段。如果需要支持多个,请在名称的末尾放置方括号:

    <input type="file" name="files[]">
    <input type="file" name="files[]">
    
  3. 确保您的 tmp 和上传目录具有正确的读写权限设置。临时上传文件夹在 PHP 设置中指定为 upload_tmp_dir

  4. 确保您的文件目的地和 tmp/load 目录没有 里面有空格。

  5. 确保页面上所有的 <form>都有 </form>关闭标签。

  6. 确保 FORM 标记具有 method="POST"。 GET 请求不支持多部分/表单数据上传。

  7. 确保文件输入标记具有 NAME 属性。ID 属性是不够的!ID 属性用于 DOM,而不用于 POST 有效负载。

  8. 确保在提交时没有使用 Javascript 禁用 <input type="file">字段

  9. 确保您没有像 <form><form></form></form>那样嵌套表单

  10. 检查 HTML 结构中是否有无效/重叠的标记,如 <div><form></div></form>

  11. 还要确保您正在上传的文件中没有任何非字母数字字符。

  12. 有一次,我花了好几个小时想弄明白为什么这事会突然发生在我身上。结果是,我修改了 .htaccess中的一些 PHP 设置,其中一个(还不确定是哪个)导致上传失败,$_FILES为空。

  13. 您可以尝试避免在 <input>标记的 name=""属性中使用下划线(_)

  14. 尝试上传非常小的文件,以缩小是否是一个文件大小的问题。

  15. 检查您的可用磁盘空间。虽然非常罕见,但是在 PHP 手册页面注释中提到:

    如果 $_ FILES 数组突然神秘地变空,即使您的表单看起来是正确的,您也应该检查临时文件夹分区可用的磁盘空间。在我的安装中,所有文件上传都在没有警告的情况下失败。咬牙切齿之后,我试图释放额外的空间,之后文件上传突然再次工作。

  16. 确保您不是通过 AJAXPOST 请求而不是通过导致页面重新加载的普通 POST 请求来提交表单。我浏览了上面列表中的每一点,最后发现 $_ FILES 变量为空的原因是我使用 AJAX POST 请求提交表单。我知道也有使用 ajax 上传文件的方法,但这可能是 $_ FILES 数组为空的有效原因。

其中一些观点的来源:
Https://web.archive.org/web/20050426084124/http://getluky.net/2004/10/04/apachephp-_files-array-mysteriously-empty/

谢谢大家的各种全面的答复。这些都很有帮助。结果发现答案很奇怪。事实证明,PHP 5.2.11不喜欢以下内容:

post_max_size = 2G

或者

post_max_size = 2048M

如果我把它改成 2047M上传就成功了。

我也有同样的问题,没有一个主题是我的错误。检查一下你的。Htaccess 文件,如果你有一个,如果“多视图”是启用。我必须解除它们。

如果您试图上传一个文件数组,那么您可能需要增加 php.ini中的 max_file_uploads,这是默认设置为 20

注意: max_file_uploads不能在 PHP.ini 之外更改。参见: PHP.ini # 50684

另一个可能的罪魁祸首是 apache 重定向。在我的例子中,我设置了 apache 的 httpd.conf,将站点上的某些页面重定向到 http 版本,将其他页面重定向到页面的 https 版本,如果它们还没有这样做的话。我有一个带有文件输入的表单的页面是配置为强制 ssl 的页面之一,但是指定为表单操作的页面被配置为 http。所以页面会将上传内容提交到 action 页面的 ssl 版本,但是 apache 会将其重定向到页面的 http 版本,发布数据(包括上传的文件)会丢失。

如果您的主脚本是 http://Some_long_URL/index.php,请注意在 action字段中指定完整的 URL (只有显式的 index.php没有http://Some_long_URL)。令人惊讶的是,如果没有,那么执行正确的脚本,但是使用 en 空的 $_ FILES!

我也有类似的问题,正如 Shamittomar 提到的,这个问题在 htaccess 中的价值是错误的。

php_value post_max_size 10MB改为 php_value post_max_size 10M

这是我发现的另一个原因: 当使用 JQueryMobile 并将 form 属性 data-ajax 设置为 true 时,FILES 数组将为空。将 data-ajax 设置为 false。

我有一个同样的问题看2个小时,是很简单的,我们检查我们的服务器配置第一。

例如:

echo $upload_max_size = ini_get('upload_max_filesize');
echo $post_max_size=ini_get('post_max_size');

任何类型的文件大小都是 :20mb,但是我们的 upload_max_size大于 20mb,而数组是 null。答案是我们的 post_max_size应该大于 upload_max_filesize

post_max_size = 750M
upload_max_filesize = 750M

我是空的 $_FILES,因为在 <form enctype="multipart/form-data" method="post">之后

</div>
<div style="clear:both"></div>

最初的代码是

<span class="span_left">Photos (gif/jpg/jpeg/png) </span>
<form enctype="multipart/form-data" method="post">
<input name="files[]" type="file" id="upload_file" />
<input type="button" id="upload" value="Upload photo" />
</form>

我决定修改和

<div>
<span class="span_left">Photos (gif/jpg/jpeg/png) </span>
<form enctype="multipart/form-data" method="post">
</div>
<div style="clear:both"></div>
<input name="files[]" type="file" id="upload_file" />
<input type="button" id="upload" value="Upload photo" />
</form>
<div style="clear:both"></div>

所以结论是,<form enctype="multipart/form-data" method="post">之后必须是 <input name, type, id,而不能是 <div>或其他一些标签

在我的情况下,正确的代码是

<div>
<span class="span_left">Photos (gif/jpg/jpeg/png) </span>
</div>
<div style="clear:both"></div>
<form enctype="multipart/form-data" method="post">
<input name="files[]" type="file" id="upload_file" />
<input type="button" id="upload" value="Upload photo" />
</form>
<div style="clear:both"></div>

没有人提到这一点,但它帮助了我,并没有很多地方在网上提到它。

确保 php.ini 设置以下键:

    upload_tmp_dir="/path/to/some/tmp/folder"

如果他们希望你使用绝对服务器文件路径,你需要与你的网站主机进行检查。您应该能够在 php.ini 文件中看到其他目录示例来确定这一点。一旦我设置了它,我就得到了 _ FILES 对象中的值。

最后,确保您的 tmp 文件夹和您移动文件的任何地方具有正确的权限,以便可以读取和写入文件。

我一直在为同样的问题而挣扎,并且测试了所有的东西,没有得到错误报告,似乎没有什么是错误的。 我有错误报告(E _ ALL) 但是我突然意识到我没有检查阿帕奇日志,瞧! 脚本中有一个语法错误... ! (缺少“}”)

所以,即使这是显而易见需要检查的东西,它也可以被遗忘..。 对我来说(linux)是:

/var/log/apache2/error.log

我也遇到了 $_ FILES 空的问题,上面的检查列表没有在.htaccess,httpd.conf 或 httpd-vhost. conf 中提到 MultiView。

如果在包含网站的目录的选项指令中设置了 MultiView,$_ FILES 将为空,即使 Content-Llength 头文件显示文件 i 已上传。

确保您的 input 元素具有“ name”属性。 <input type="file" name="uploadedfile" />

如果这个文件丢失,$_ FILES 将为空。

在表单中添加 enctype="multipart/form-data"非常重要,例如

<form action="upload.php" method="post" enctype="multipart/form-data">
Select image to upload:
<input type="file" name="fileToUpload" id="fileToUpload">
<input type="submit" value="Upload Image" name="submit">
</form>

我遇到了同样的问题,发现我的 IDE 也是问题的一部分。我是直接从 IDE (PHPStorm)启动调试器,而不是直接使用浏览器。IDE 生成的 URL 是这样的:

"...localhost:63342/CB_Upload/index.php?_ijt=j2hcbacqepj87bvg66ncuohvne"

只要用:

"...localhost/CB_Upload/index.php"

我的设置是 PC/Windows 10/WAMPSERVER 3.0.664位

如果您正在使用 JQueryMobile

Ajax 不支持使用带有文件输入的多部分表单。在这种情况下,您应该使用 data-ajax = “ false”来装饰父表单,以确保表单正确地提交给服务器。

<form action="upload.php" method="post" enctype="multipart/form-data"  data-ajax="false">
Select image to upload:
<input type="file" name="fileToUpload" id="fileToUpload">
<input type="submit" value="Upload Image" name="submit">
</form>

检查你的 php.ini 是否有 Able _ post _ data _ reading = On,因为:

禁用此选项 导致 $_ POST 和 $_ FILES 不被填充。读取 postdata 的唯一方法是通过 php://input 流包装器

http://php.net/manual/en/ini.core.php#ini.enable-post-data-reading

如果您在共享宿主环境中,请不要信任由 sys_get_temp_dir提供的临时文件夹位置。

这里还有一件事情需要检查,还没有被提到..。

当然,我假设 PHP 脚本存储临时文件上传的文件夹是 /tmpecho sys_get_temp_dir() . PHP_EOL;返回 /tmp的事实加强了这种信念。而且,echo ini_get('upload_tmp_dir');不返回任何值。

为了验证上传的文件确实短暂地出现在我的 /tmp文件夹中,我在脚本中添加了一条 sleep(30);语句(建议使用 给你) ,并导航到 cPanel File Manager 中的 /tmp文件夹中以找到该文件。然而,无论如何,上传的文件在那里都找不到。

我花了好几个小时试图找出原因,并实施了所有的建议。

最后,在搜索我的网站文件查询 tmp之后,我发现我的网站在不同的目录中包含其他名为 tmp的文件夹。我意识到 我的 PHP 脚本实际上是把上传的文件写到 .cagefs/tmp(为了查看这个文件夹,必须在 cPanel 中启用 “显示隐藏文件”设置)

那么,为什么 sys_get_temp_dir函数返回不准确的信息呢?

以下是 PHP.net 网站对 sys_get_temp_dir的解释(也就是最上面的评论) :

如果在 Systemd 具有 PrivateTmp = true (其中 是 CentOS 7的默认版本,也许还有其他更新的发行版) 函数只返回“/tmp”,不返回 true, 有点动态的路径。

这篇 SO 文章也深入探讨了这个问题:

从您正在使用的页面中分离表单 进入一个简单的 php 页面,其中包含 只测试 php 代码,并像这样进行测试。

任何引导程序或 Java 脚本都可能被清除 那是我的案子

如果您使用的是 AJAX 而不是 Form 提交,那么请确保将请求头 Content-Type设置为 multipart/form-data; boundary=myAwesomeBoundary',其中 myAwesomeBoundary是分隔请求主体部分的唯一字符串。我犯了一个错误,覆盖了 Content-Type的头设置为只有 multipart/form-data没有设置 boundary。解决方案是不覆盖标题,但让浏览器为我生成它。