将文件上传到PHP时,为什么$ _FILES为空?

时间:2010-08-27 18:01:48

标签: php apache file-upload

我的Windows 7计算机上安装了WampServer 2。我正在使用Apache 2.2.11和PHP 5.2.11。当我尝试从表单上传任何文件时,它似乎上传,但在PHP中,$_FILES数组为空。 c:\wamp\tmp文件夹中没有文件。我已配置php.ini以允许文件上传等。 tmp文件夹具有当前用户的读/写权限。我很难过。

HTML:

<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
    <form enctype="multipart/form-data" action="vanilla-upload.php" method="POST">
        Choose a file to upload: <input name="uploadedfile" type="file" /><br />
        <input type="submit" value="Upload File" />
    </form>
</body>
</html>

PHP:

<?php
echo 'file count=', count($_FILES),"\n";
var_dump($_FILES);
echo "\n";
?>

22 个答案:

答案 0 :(得分:429)

以下是PHP中文件上传的检查表:

  1. 检查php.ini:
    file_uploads = On
    post_max_size = 100M
    upload_max_filesize = 100M

    • 如果您使用的是共享托管且无法访问.htaccess,则可能需要使用.user.iniphp.ini
    • 确定 你正在编辑正确的ini文件 - 使用phpinfo()功能验证您的身份 实际上正在应用设置。
    • 另外请确保不这样做 拼写错误的大小 - 它应该是100M 而不是 100MB
  2. 确保您的<form>代码具有enctype="multipart/form-data"属性。没有其他标签可以使用,它必须是您的FORM标签。仔细检查拼写正确。仔细检查多部分/表单数据是否被STRAIGHT QUOTES包围,而不是从Word或网站博客中粘贴的智能引号(WordPress将直引号转换为角度报价!)。如果页面上有多个表单,请确保它们都具有此属性。手动输入,或尝试手动输入直接单引号。

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

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

  5. 确保您的文件目标和tmp / upload目录没有 其中有空格。

  6. 确保您网页上的所有<form>都有</form>个关闭代码。

  7. 确保您的FORM标记为method="POST"。 GET请求不支持多部分/表单数据上传。

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

  9. 确保您在提交时未使用Javascript停用<input type="file">字段

  10. 确保您没有嵌套<form><form></form></form>

  11. 等表单
  12. 检查HTML结构中是否存在<div><form></div></form>

  13. 等无效/重叠标记
  14. 还要确保您上传的文件中没有任何非字母数字字符。

  15. 有一次,我花了好几个小时试图弄清楚为什么会突然发生这种情况。事实证明我修改了.htaccess中的一些PHP设置,其中一个(不确定哪个)导致上传失败并且$_FILES为空。

    < / LI>
  16. 您可以尝试在_代码

  17. name=""属性中避免使用下划线(<input>
  18. 尝试上传非常小的文件,以缩小是否存在文件大小问题。

  19. 检查可用磁盘空间。虽然非常罕见,但在PHP Manual page comment中提到了

      

    如果$ _FILES数组突然出现空洞,即使表单看起来正确,也应该检查临时文件夹分区的可用磁盘空间。在我的安装中,所有文件上传都失败而没有警告。在咬牙切齿之后,我尝试释放额外的空间,之后文件上传突然再次起作用。

  20. 请确保您没有通过AJAX POST请求而不是正常的POST请求提交表单,导致页面重新加载。我浏览了上面列表中的每一点,最后发现我的$ _FILES变量为空的原因是我使用AJAX POST请求提交表单。我知道有一些方法可以使用ajax上传文件,但这可能是你的$ _FILES数组为空的正当理由。

  21. 其中一些要点的来源:
    http://getluky.net/2004/10/04/apachephp-_files-array-mysteriously-empty/

答案 1 :(得分:72)

对于您似乎已正确设置该部分的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?


答案 2 :(得分:30)

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>

答案 3 :(得分:14)

感谢大家提供各种全面的回复。这些都非常有帮助。答案结果证明是非常奇怪的。事实证明PHP 5.2.11不喜欢以下内容:

post_max_size = 2G

post_max_size = 2048M

如果我将其更改为2047M,则上传有效。

答案 4 :(得分:6)

我找到了另一个原因: 使用JQuery Mobile并将表单属性data-ajax设置为true时,FILES数组将为空。所以将data-ajax设置为false。

答案 5 :(得分:5)

我有同样的问题看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

答案 6 :(得分:3)

确保您的输入元素具有&#39;名称&#39;属性。 <input type="file" name="uploadedfile" />

如果缺少,$ _FILES将为空。

答案 7 :(得分:3)

我正在努力解决同样的问题并测试所有内容,没有得到错误报告,似乎没有任何错误。 我有error_reporting(E_ALL) 但突然间我意识到我没有检查过apache日志并且vo! 脚本上有语法错误......! (缺少“}”)

所以,即使这是值得检查的事情,也可能会被遗忘...... 在我的情况下(linux)它位于:

/var/log/apache2/error.log

答案 8 :(得分:2)

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

确保您的php.ini设置以下密钥:

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

如果您希望使用绝对服务器文件路径,则需要检查您的webhost。您应该能够在php.ini文件中看到其他目录示例来确定这一点。一旦我设置它,我在_FILES对象中得到了值。

最后确保您的tmp文件夹以及移动文件的位置具有正确的权限,以便可以读取和写入。

答案 9 :(得分:2)

检查你的php.ini上的 enable_post_data_reading = On ,因为:

  

禁用此选项会导致$ _POST和$ _FILES无法填充。读取postdata的唯一方法是通过php://输入流包装器。 (...)

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

答案 10 :(得分:2)

另一个可能的罪魁祸首是apache重定向。在我的情况下,我设置了apache的httpd.conf,将我们网站上的某些页面重定向到http版本,将其他页面重定向到页面的https版本,如果它们还没有。我有一个带有文件输入的表单的页面是配置为强制ssl的页面之一,但指定为表单操作的页面配置为http。因此页面会将上传内容提交到操作页面的ssl版本,但是apache会将其重定向到页面的http版本,而后期数据也会丢失。

答案 11 :(得分:2)

如果您尝试上传文件数组,则可能需要在php.ini中增加max_file_uploads,默认设置为20

注意max_file_uploads无法在php.ini之外进行更改。见PHP "Bug" #50684

答案 12 :(得分:1)

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

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

并且只使用:

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

工作得很好。我的设置是PC / Windows 10 / WAMPSERVER 3.0.6 64位

答案 13 :(得分:0)

我是空的$_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>

答案 14 :(得分:0)

我有类似的问题,而且这个问题在shattomar中提到的htaccess中的错误值。

php_value post_max_size 10MB更改为php_value post_max_size 10M

答案 15 :(得分:0)

如果您的主要脚本为http://Some_long_URL/index.php,请务必在{{1}中指定完整网址(明确index.php <{1}}) }字段。令人惊讶的是,如果没有,则执行正确的脚本,但使用空的$ _FILES!

答案 16 :(得分:0)

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

如果您在包含该网站的目录的options指令中设置了MultiViews,则$ _FILES将为空,即使Content-Length标头显示我上传的文件。

答案 17 :(得分:0)

如果您使用的是JQuery Mobile

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>

答案 18 :(得分:0)

我遇到了同样的问题,没有一个主题是我的错误。检查.htaccess文件,如果有的话,如果启用了“MultiViews”。我不得不禁用它们。

答案 19 :(得分:0)

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

还有一件事需要检查,但尚未提及...

我自然地以为,我的PHP脚本存储临时文件上载的文件夹为/tmpecho sys_get_temp_dir() . PHP_EOL;返回/tmp的事实进一步强化了这一信念。另外,echo ini_get('upload_tmp_dir');不返回任何内容。

为验证上传的文件确实确实短暂出现在我的/tmp文件夹中,我在脚本中添加了sleep(30);语句(如建议的here)并导航到我的{{ 1}}文件夹中的cPanel文件管理器中找到该文件。但是,无论如何,都无法在此找到上传的文件。

我花费了数小时试图确定原因,并实施了此处提供的所有建议。

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

那么,为什么.cagefs/tmp函数返回的信息不正确?

这是PHP.net网页上sys_get_temp_dir的说明(即最上面的注释):

  

如果在Linux系统上运行,其中systemd具有PrivateTmp = true(   是CentOS 7和其他较新发行版的默认设置),   函数将只返回“ / tmp”,而不是true,时间更长,   有点动态的路径。

此SO帖子也探讨了这个问题:

答案 20 :(得分:0)

从您正在使用的页面上分离表格 进入一个具有以下形式的简单php页面: 仅php代码,并像这样进行测试。

任何引导程序或Java脚本都可能清除 文件[]。那是我的情况

答案 21 :(得分:0)

如果您使用 AJAX 而不是表单提交,请确保将请求标头 Content-Type 设置为 multipart/form-data; boundary=myAwesomeBoundary',其中 myAwesomeBoundary 是分隔请求正文部分的唯一字符串。我错误地将 Content-Type 标头设置为仅 multipart/form-data 而未设置 boundary。解决方法是不覆盖标头,而是让浏览器为我生成它。