网页、php脚本的编码问题
对于程序的编码问题,做一次总结,我们清楚,从对象来说,编码可能涉及到三到四个对象
一、首先是请求终端:
这个请求终端有可能是浏览器端,从浏览器端发起网页请求;Ajax请求;也有可能是程序内部的Api调用。
a、先看浏览器端和web服务器端的数据交互采用的编码符合什么准则
浏览器端的输入分成两种情况,
第一种情况是:在浏览器的地址栏输入url地址,在带有汉字的情况下的编码选择,这种情况是没有指定传输编码,测试中发现,IE,firefox,chrome会将地址栏中
浏览器 | 默认传输编码 |
IE | gbk |
firefox | utf-8 |
chrome | utf-8 |
第二种情况是:在网页中输入的汉字,再和服务器交互过程中的编码选择
这种情况的汉字传输编码,会和网页设置的编码有关。如果charset是gbk,则以gbk形式传递参数。
<head> <meta http-equiv="Content-Type" content="text/html; charset=gbk" /> </head>
b、Ajax请求
实际上ajax请求和第一种情况,从地址栏输入url发起请求一样,实际上都是未指定请求参数的编码,在这种情况下,
c、php程序内部的Api请求
我们在php程序中会使用到curl或者简单的使用file_get_contents()方法去调用Api,在调用过程中,我们会带上参数。如果这个参数是汉字
那么出现两种情况
情况一,参数是外界输入
情况二,参数是脚本定义的
我们写个简单的实验看一下,首先,我们写一个脚本testcode.php,采用GBK编码保存
<?php if(isset($_REQUEST['m'])){ $pram1 = $_REQUEST['m']; } $pram2 = "你好"; $filename = "http://10.221.20.175/test/example.php?p1=$pram1&p2=$pram2"; $s = file_get_contents($filename); var_dump($s);
脚本2 example.php 采用UTF-8保存只是输出值
<?php if(isset($_REQUEST['p1'])){ echo $_REQUEST['p1']; } else{ echo "p1."; } if(isset($_REQUEST['p2'])){ echo $_REQUEST['p2']; } else{ echo "p2."; }
我们在浏览器端请求 http://10.221.20.175/test/testcode.php?m=达人
从图中,我们一步一步查看。
1、第一步,服务端抓包,可以看出,参数“达人”被转码,转成了%E8%BE%BE%E4%BA%BA, 实际上,汉字”达人“是被
转成了UTF8编码,编码的每个字节前用"%"做了标识
2、第二步,web服务器和php-fpm交互,LNNP环境下,一般会启动php-fpm和nginx做交互,可以看到,交互中,nginx未修改汉字"达人"的编码
3、第三步,testcode.php脚本被php引擎读入,发现file_get_contents,需要请求链接,再发起请求到nginx服务器。我们能看到 这个请求链接包含两个参数 /test/example.php?p1=......&p2=.... ,很明显,从脚本看,p1这个参数是UTF8编码,p2这个参数是gbk编码。
4、第四步,nginx请求处理file_get_contents请求,将请求转给php-fpm
5、第五步,php引擎接到第四步的请求,读入example.php脚本处理,我们看一下,处理的返回值。返回的字符串编码是 e8be bee4 baba c4e3 bac3 明显看出来,前面是三个字节是utf8编码,表示“达人”,后面两个是gbk编码表示“你好”
6、第六步,nginx在收到第五步的返回值后,会将结果返回给testcode.php脚本处理程序,我们可以看出,返回结果被放在610d0a字符编码后,基本在最后,结束符编码是0d 0a30 0d0a 0d0a
7、第七步、 testcode.php脚本在处理完后,会将结果返回给nginx服务器,返回处理值中,对于脚本的返回值,做了gzip压缩,这主要是因为在请求头上有接受gzip压缩(是否可以看出,请求头上的是否接受压缩,是php引擎做的?)
8、第八步、nginx服务器和客户端交互,在这里,实际上返回值被gzip压缩了。所以看不到传递的值,但是从客户端解压缩后,我们可以看到,显示的结果和第7步返回给nginx的是一致的。
从上面的情况,我们大概能得到这样的结论:
这个结论是建立在简单的实验基础上,未参照php源码,可能会有不一致的地方,但是,不管怎么样,我们可以认为,
1、在php程序中,如果不采用转码函数,如,iconv()等,那么php本身不会自动将输入参数转成代码本省的参数
2、在php程序中,程序内部定义的汉字,按照程序保存时候的编码传递。