有的时候会遇到上传文件失败的问题,肿么办呢?大多数人会说,上传目录没有写权限吧,权限开成 777 就好了嘛,后台没有开启对应的选项吧,用户组设置上传
文件限制大小了有木有?诚然,这些都是上传文件失败的几种常见原因,但这些代表了上传问题的根源吗,事实告诉我们,上传错误可以是多种多样,花样百出的。
下面我就详细说说上传文件的过程。

【上传文件是怎样炼成的?】

大家都知道上传文件,但文件是怎么上传的呢?
我们来看一段简单的代码:
假设我们使用 PHP 作为服务器端的脚本语言

  1. <form enctype="multipart/form-data" action="upload.php" method="post">
  2.     <input name="userfile" type="file">  
  3.     <input type="submit" value="上传文件">
  4. </form>

这是上传文件的一个简单 HTML 代码例子
我们指定了 form 标签的 enctype 属性为 multipart/form-data,代表了不对表单内字符进行编码,一般在使用包含文件上传控件的表单中使用。
当我们点击按钮提交表单后,浏览器会将请求提交的服务器,服务器保存文件,看似文件上传已经成功,然而这才是文件上传的开始而已呀。
这时候 upload.php 开始执行,与常用的 GETPOST 的请求不同,文件上传到服务器后,并没有直接保存到我们需要保存的目录,而是暂存在一个临时文件目录下。
upload.php 需要做的就是把这个文件放到我们真正需要存放的目录中。
上传文件的信息会作为一个全局变量保存在 $_FILES 数组中。
刚才例子中的文件的信息将会保存在 $_FILES[『userfile』] 中 (因为我们表单中上传的字段命名为 userfile)
$_FILES['userfile']['name'] 客户端机器文件的原名称。
$_FILES['userfile']['type'] 文件的 MIME 类型,需要浏览器提供该信息的支持,例如 「image/gif」 。
$_FILES['userfile']['size'] 已上传文件的大小,单位为字节。
$_FILES['userfile']['tmp_name'] 文件被上传后在服务端储存的临时文件名。 (这个很重要,不然就找不到文件了啊)
$_FILES['userfile']['error'] 和该文件上传相关的错误代码。 (如果有错误,那么之前的几个变量都会是空值,错误将在后面详述)
然后程序根据这些信息,将文件保存到相应的目录下,过程比较简单,代码就不做详细列出了。

【上传失败是怎样炼成的?】
如果上文中的过程顺利,没有错误,那么我们上传工作就完成啦。但老天总不会让事情发展的如此顺利,于是各种的上传失败出现了。
我们以论坛上传附件为例,分析下上传的错误可能都有哪些。
我把错误归纳为三类:

第一类,程序限制。
故名思议,就是 Discuz! 的上传限制机制限制了,其实 Discuz! 已经给出各个上传失败的提示了,只是如果使用批量上传是无法看到所有提示的嗯,所以我们用单个文件上传来测试。

下面列出上传限制的一些条件,并会给出一些设置的建议 (这些限制会在上传失败时提示):

  1. 1. 不支持此类扩展名

在用户组--编辑--附件相关--允许附件类型、版块--帖子选项--附件类型中可以设定支持上传的附件类型。
同时,注意下全局--附件类型尺寸--对应的附件类型允许的大小。

  1. 2. 服务器限制无法上传那么大的附件

这个是由于服务器限制了文件大小导致的 (后面会讲到),还有,上传 0kb 的文件也会提示这个嗯

  1. 3. 用户组限制无法上传那么大的附件

用户组--编辑--附件相关--论坛最大附件尺寸,设置大一些的值,或者设置为 0 不限制。

  1. 4. 文件类型限制无法上传那么大的附件

全局--附件类型尺寸--对应的附件类型允许的大小。

  1. 5. 今日你已无法上传更多的附件

用户组--编辑--附件相关--每天最大附件数量,设置大一些的值,或者设置为 0 不限制。

  1. 6. 今日你已无法上传那么大的附件

用户组--编辑--附件相关--每天最大附件总尺寸,设置大一些的值,或者设置为 0 不限制。

  1. 7. 非法操作

表单 hash 值出错,刷新页面再提交,如果还是失败则还原模板,更新缓存。

  1. 8. 没有合法的文件被上传

上传文件属于非法文件,选择正常的文件重新发送。

  1. 9. 请选择图片文件

选择上传图片时,选择图片类型的文件,而不是其他类型的。

第二类,服务器限制。
当上传文件后提示:

  1. 1. 服务器限制无法上传那么大的附件

检查下 PHP 的相关设置。 php.ini 中的 upload_max_filesize,post_max_size 两个变量的值是否小于上传文件的大小。

  1. 2. 附件文件无法保存

Discuz! data 目录是否具有读写权限,建议设置 data 目录包括其子目录权限为 777

第三类,其他错误。
除了以上的常规错误之外,还有一些其他疑难症状出现,在此做一个收集和汇总:
特例一:
出现状况:
1. 服务器环境:iis+php,小文件上传成功,大文件上传失败,表现为有上传进度,而到最后提示上传失败。
排查情况:
1.Discuz! 程序无修改,正常。
2. 后台上传限制关闭,正常。
3. 服务器目录权限正确,正常。
4. 服务器上传大小限制变量设置正确,正常。
5. 上传文件本身没有问题,正常。
按理来说,一切配置都没有问题,为什么上传还是提示失败呢?
原因分析:
为了验证原因,我们跟随程序排查,发现并没有进入 php 程序的上传流程,而是在上传到服务器临时目录的过程中返回了一个错误:

  1. The FastCGI process exceeded configured

原来是 FastCGI 进程超时了
解决方法:
找到 FastCgi 的配置文件 「fcgiext.ini」,位于目录 「C:WINDOWSsystem32inetsrv」 下。
在 「fcgiext.ini」 最末 php 的配置内容下增加一些参数 (如原先就有参数,则对原有参数做修改),修改如下:

  1. [Types]
  2. php=PHP
  3. [PHP]
  4. InstanceMaxRequests=10000
  5. EnvironmentVars=PHP_FCGI_MAX_REQUESTS:10000
  6. RequestTimeout=500
  7. ActivityTimeout=900

以上是文件上传可能失败的原因和解决方法,可能有疏漏,望有识之士指出~