php的$_FILES如何生成以及如何与上传文件对象产生联系

一、前言

      写这篇博客的原因是因为,在上传文件的时候,我们都知道要用$_FILES变量来获取上传的内容,但是$_FILES是什么使用开始有值的呢?我们上传的是二进制参数,为什么在后台不能通过$_POST打印出来呢?

这些疑问一直困扰着博主,总感觉是知其然不知其所以然,这次就来好好的研究下$_FILES

二、问题的产生,后端无法打印上传的参数

1、首先POST上传的参数如下:

files(binary)    //F12看到的参数是这样的,binary代表是二进制的文件流

2、后端打印files参数

var_dump($_POST);  //发现没有files参数

3、打印input[type=file]的value

C:\fakepath\job.json    //并不是php的tmp临时文件,和咱们平时打印$_FILES看到的不一样

4、打印$_FILES返回数据,代表文件已经传过去了

问题: 那么什么时候$_FILES开始有值的呢?我们传递的files参数又去哪里了,为什么是打印是空

三、$_FILES是如何获取内容的呢

      博主在网上查了很多,大部分博客都是简单的介绍下$_FILES的内容参数,并没有解释这个东西是怎么来的,直到碰到鸟哥的一篇文章,博主才幡然醒悟。

鸟哥博客:http://www.laruence.com/2009/09/26/1103.html

1、大概解释
      在客户端执行上传之后,不管是ajax还是普通表单还是formData,本质上都是通过http上传的,php会获取http的头部,并且识别出来这个是上传操作,然后找到rfc1867的处理函数rfc1867_post_handler, 从而调用这个handler, 来分析POST来的数据。

关于rfc1867参考:https://blog.csdn.net/yizhou35/article/details/12358325

2、流程

分析数据可以简单分为:
(1)区分普通数据和文件上传数据(是否有name,是否有filename
(2)读取用户上传的部分自定义设置,如MAX_FILE_SIZE.
(3)如果是文件上传,就调用代码生成一个临时文件,返回文件名
(4)验证文件名称合法,name合法等
(5)读取文件内容,写入到临时文件,生成FILE变量,有命名的上传,如images,则设置$_FILES['images'] = 文件信息,大小吗,临时目录等,没有命名上传的话,则为$_FILES['tmp_name']

      这样就能解释的通了,原来这个$_FILES变量是php解析传过来的数据,在有文件上传的时候,通过一系列操作赋值进去的。

四、那么为什么打印files变量为空

      这部分本来是一直不理解,后来发现在php处理解析POST传过来的数据的时候,是把普通数据和文件流数据分开处理的,是if和elseif的关系,生成的变量也是不一样的。然后可以参考:
鸟哥的博客:http://www.laruence.com/2008/11/07/581.html
      在处理完数据之后,后续的$_POST大变量生成的时候,是只针对普通的数据,而传过去的文件数据是写入到了$_FILES里面的。

      这样的话,相当于POST中的文件流被php特殊处理了,并且和普通的参数进行了区分,赋值为$_FILES变量。具体代码可以参考(PS:这是c的代码,博主看不懂,只能看个大概,哈哈):

if ((cd = php_mime_get_hdr_value(header, "Content-Disposition"))) {
     char *pair=NULL;
     int end=0;
 
     while (isspace(*cd)) {
          ++cd;
     }
 
     while (*cd && (pair = php_ap_getword(&cd, ';')))
     {
          char *key=NULL, *word = pair;
 
          while (isspace(*cd)) {
               ++cd;
          }
 
          if (strchr(pair, '=')) {
               key = php_ap_getword(&pair, '=');
 //--------------这里开始处理出具
               if (!strcasecmp(key, "name")) {
                    //获取name字段
                    if (param) {
                         efree(param);
                    }
                    param = php_ap_getword_conf(&pair TSRMLS_CC);
               } else if (!strcasecmp(key, "filename")) {   //----------------这里处理文件流数据
                    //获取filename字段
                    if (filename) {
                         efree(filename);
                    }
                    filename = php_ap_getword_conf(&pair TSRMLS_CC);
               }
          }
          if (key) {
               efree(key);
          }
          efree(word);
     }

      这下世界都安静了,咱们的疑问全部得到解决。不得不说,看源码是一种很好的方式,只可惜博主水平不够,只能看着别人分析源码的博客来解决自己的问题。不过这种找到原理的感觉是真的不错,从此不再是“知其然,不知其所以然”!

end

  • 10
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

铁柱同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值