手机浏览 RSS 2.0 订阅 膘叔的简单人生 , 腾讯云RDS购买 | 超便宜的Vultr , 注册 | 登陆
浏览模式: 标准 | 列表2009年01月的文章

参数编码 完全解决方案[ZZ]

GET和POST接收编码格式不一样?说实话,原先没有考虑过这些问题。因为在一个项目中,程序的编码由项目开始到结束肯定都会一样的,当然在ajax处理的时候可能会有点变化。毕竟ajax的东西采用了UTF8进行传递。除此之外,其他的编码一般来说都是一致的。在看到这篇文章的时候,觉得不错。同时也是提醒一下自己需要注意。
因为他的代码是.NET的,临时转载,就不翻译成PHP了,看看别人的思路就行了。。。
原文地址:http://www.cnblogs.com/zhangziqiu/archive/2009/01/20/encoding.html
原文:

在查阅了一天资料,做了很多的试验, 精简提炼语言后, 完成了下面的文章.我发现在项目中太多的程序员对编码,尤其是Web程序中的中文参数编码一知半解.本文将作为一种规范提出, 以后将会应用到我制作的项目中.希望能够对大家有所启示.

[参数编码规范]  

[原则]

避免在get或者post参数时直接传递中文字符.每次都经过指定格式的url编码后再传递.

[原因]

传递中文字符时,自动的编码解码格式和浏览器与服务器的设置有关.

测试Firefox3和IE6的Get方式发送中文参数, Firefox默认使用UTF-8格式编码中文参数, 而IE6即使在高级设置中设置了"总是以 UTF-8 发送URL", 仍然自动使用GB2312编码中文参数.

对于服务器端我们可以自由的控制解码的格式.但是往往是通过更改服务器配置进行全局的统一设置.比如对于ASP.NET程序.可以在Web.Config中设置服务器段的编码和解码格式:

XML/HTML代码
  1. <globalization culture="zh-CN" uiCulture="zh-CN" requestEncoding="UTF-8" responseEncoding="gb2312" />   

但是我们没法控制浏览器端行为.用户可能使用不同的浏览器.

   

[解决方案]

一.统一默认的编码格式

1.设置服务器端的编码格式为UTF-8

2.传递参数全部进行编码,.服务器端(C#)使用Server.UrlEncode方法,客户端(javascript)使用encodeURIComponent方法.

说明:

客户端的javascript函数encodeURIComponent只能使用UTF-8编码格式. 所以需要设置服务器端request和response都为UTF-8.

缺陷是如果某些合作伙伴必须传递其他的编码格式的参数, 则服务器端或获取到乱码.此方案实现简单,适合大部分场景.

   

二.通过编码参数指定编码格式

为了解决可能存在的无法统一编码格式的问题, 我们使用一个参数"encoding"来显示的指定编码格式.encoding参数需要在所有的请求中传递,无论是get还是post.

1.对于javascript客户端编码而言, 仍然使用encodeURIComponent方法编码, 此时指定encoding参数的值为"UTF-8".

2.对于传入给服务器端的 其他编码格式, 比如GB2312, 我们不能使用默认的Request.Form或者QueryString方法进行编码.因为服务器端的编码格式可能设置为了UTF-8.此时使用 Request.Form或者QueryString会自动使用服务器端指定的编码格式进行解码. 所以需要使用下面的方法自己处理请求,获取参数:

C#代码
  1. /**//// <summary>  
  2. /// 根据指定的编码格式返回请求的参数集合 ziqiu.zhang 2009.1.19  
  3. /// </summary>  
  4. /// <param name="request">当前请求的request对象</param>  
  5. /// <param name="encode">编码格式</param>  
  6. /// <returns>键为参数名,值为参数值的NameValue集合</returns>  
  7. public static NameValueCollection GetRequestParameters(HttpRequest request, string encode)  
  8. {  
  9.     NameValueCollection result = null;  
  10.     Encoding destEncode = null;  
  11.   
  12.     //根据指定的编码格式获取Encoding对象  
  13.     if (!String.IsNullOrEmpty(encode))  
  14.     {  
  15.         try  
  16.         {  
  17.             //获取指定的编码格式  
  18.             destEncode = Encoding.GetEncoding(encode);  
  19.         }  
  20.         catch   
  21.         {  
  22.             //如果获取指定编码格式失败,则默认为null  
  23.             destEncode = null;  
  24.         }  
  25.     }  
  26.   
  27.     //根据不同的HttpMethod方式,获取请求的参数.  
  28.     if (request.HttpMethod == "POST")  
  29.     {  
  30.         if (null != destEncode)  
  31.         {  
  32.             Stream resStream = request.InputStream;  
  33.             byte[] filecontent = new byte[resStream.Length];  
  34.             resStream.Read(filecontent, 0, filecontent.Length);  
  35.             string postquery = destEncode.GetString(filecontent);  
  36.             result = HttpUtility.ParseQueryString(postquery, destEncode);  
  37.         }  
  38.         else  
  39.         {  
  40.             result = request.Form;  
  41.         }  
  42.     }  
  43.     else  
  44.     {  
  45.         if (null != destEncode)  
  46.         {  
  47.             result = System.Web.HttpUtility.ParseQueryString(request.Url.Query, destEncode);  
  48.         }  
  49.         else  
  50.         {  
  51.             result = request.QueryString;  
  52.         }  
  53.     }  
  54.   
  55.     //返回结果  
  56.     return result;  
  57. }  
此方法的返回值是一个NameValueCollection集合.客户端实例代码如下:
C#代码
  1. protected override void OnLoad(EventArgs e)  
  2. {  
  3.     string sUrl = String.Empty;//来源页Url  
  4.     string tUrl = String.Empty;//目标页Url  
  5.     string encoding = String.Empty; //编码格式  
  6.   
  7.     Response.Clear();  
  8.   
  9.     try  
  10.     {  
  11.         //获取编码格式  
  12.         if (Request.HttpMethod.ToUpper().Trim() == "POST")  
  13.         {  
  14.             if (!String.IsNullOrEmpty(Request.Form["encoding"]))  
  15.             {  
  16.                 encoding = Request.Form["encoding"].ToUpper();  
  17.             }  
  18.         }  
  19.         else  
  20.         {  
  21.             if (!String.IsNullOrEmpty(Request.QueryString["encoding"]))  
  22.             {  
  23.                 encoding = Request.QueryString["encoding"].ToUpper();  
  24.             }  
  25.         }  
  26.   
  27.         //根据编码获取传递的参数列表  
  28.         NameValueCollection paramList = EncodeUtility.GetRequestParameters(Request, encoding);  
  29.   
  30.         //获取OrderFrom判断需要的参数  
  31.         sUrl = paramList["surl"];  
  32.         tUrl = paramList["turl"];  
  33.   
  34.         //获取OrderFrom的Cookies字符串  
  35.         if ( !( String.IsNullOrEmpty(sUrl) && String.IsNullOrEmpty(tUrl) ) )  
  36.         {  
  37.             Response.Write(OrderFromBL.OrderFromAnalysis(sUrl, tUrl));  
  38.         }  
  39.     }  
  40.     catch(Exception ex)  
  41.     {  
  42.         WebLog.CommentLog.CommonLogger.Error("OrderFromAjaxProxy.aspx页发生错误", ex);  
  43.     }  
  44.           
  45.     Response.End();  
  46. }  

如果没有传入encoding参数,则使用服务器端默认的编码方式.

   

[总结]

两种解决方案首先都是要做到避免使用浏览器的中文自动编码, 中文参数一定要先编码再传递. 同时统一客户端和服务器端的编码格式.

   [知识扩展]

   

[浏览器端的编码方式]

Get:

对于Get方式发送的请求, 不同的浏览器使用不同的编码方式自动为中文参数编码.比如:Firefox/3.0.5 使用UTF-8, IE6使用GB2312.

Post:

对于Post方式发送的 请求, 表单中的参数值对是通过request body发送给服务器,此时浏览器会根据网页的ContentType("text/html; charset=GBK")中指定的编码进行对表单中的数据进行编码,然后发给服务器。在HTML代码的Head中添加:
<meta http-equiv="Content-Type" content="text/html;charset=gb2312" />

Firefox/3.0.5 会使用根据charset中设置的编码格式编码post的中文参数.

IE6不起作用.

实验表明使用客户端浏览器默认编码格式具有不确定性.所以传递中文时我们要手工编码参数.

   

[Javascrip中的编码]

Javascrip语言中编码解码相关的方法主要有:

函数名称

函数说明

解释

escape()

escape() 函数可对字符串进行编码,这样就可以在所有的计算机上读取该字符串。

该方法不会对 ASCII 字母和数字进行编码,也不会对下面这些 ASCII 标点符号进行编码: - _ . ! ~ * ' ( ) 。其他所有的字符都会被转义序列替换。

   

[已过时] 请使用 encodeURI() 或 encodeURIComponent()

unescape()

unescape() 函数可对通过 escape() 编码的字符串进行解码。

该函数的工作原理是这样的:通过找到形式为 %xx 和 %uxxxx 的字符序列(x 表示十六进制的数字),用 Unicode 字符 \u00xx 和 \uxxxx 替换这样的字符序列进行解码。

   

[已过时] 请使用 decodeURI() 或 decodeURIComponent()

encodeURI()

encodeURI() 函数可把字符串作为 URI 进行编码。

  

该方法不会对 ASCII 字母和数字进行编码,也不会对这些 ASCII 标点符号进行编码: - _ . ! ~ * ' ( ) 。

该方法的目的是对 URI 进行完整的编码,因此对以下在 URI 中具有特殊含义的 ASCII 标点符号,encodeURI() 函数是不会进行转义的:;/?:@&=+$,#

   

[提示] 如果 URI 的参数中含有不能转移的字符,则应当使用 encodeURIComponent() 方法分别对各参数进行编码。

decodeURI()

decodeURI() 函数可对 encodeURI() 函数编码过的 URI 进行解码。

  

  

encodeURIComponent()

encodeURIComponent() 函数可把字符串作为 URI 组件进行编码。

  

该方法不会对 ASCII 字母和数字进行编码,也不会对这些 ASCII 标点符号进行编码: - _ . ! ~ * ' ( ) 。

其他字符(比如 :;/?:@&=+$,# 这些用于分隔 URI 组件的标点符号),都是由一个或多个十六进制的转义序列替换的。

   

[提示] 此方法会编码URI中的特殊字符

decodeURIComponent()

decodeURIComponent() 函数可对 encodeURIComponent() 函数编码的 URI 进行解码。

  

   

举例
document.write(encodeURIComponent("http://www.w3school.com.cn")+ "<br />")
document.write(encodeURI("http://www.w3school.com.cn")+ "<br />")

 结果
http%3A%2F%2Fwww.w3school.com.cn

http://www.w3school.com.cn

总结
对于一个URI(URL也是一中URI),如果我们希望将它作为完整的网址发送请求, 但是上面带有中文, 则应该使用encodeURI方法.

如果是要编码参数,则应该使用encodeURIComponent.

 


Tags: 编码, get, post, 方案

按照AdSense要求投放广告代码

虽然我的google adsense广告几乎没有人点,但是今天看到adsense小组说的重复投放的事情,还是有必要转帖一下,帮助其他人,免得重复 。。。

AdSense中文小组告诉我们:

自从我们发布了服务 器端广告设置这个功能以后,大家修改代码就更加方便了。Google AdSense代码投放的最好办法是直接通过帐户获取代码并嵌入到要投放的网站页面源代码中,但是我们发现有一些网站调整了AdSense广告代码的展 示。比如在一部分文学网站和一些内容管理系统中有类似于此的AdSense代码投放方式:

<div id="span_ad_01" style="display:none">
<script type="text/javascript"><!--
google_ad_client = "pub-1234512345123451";
google_ad_slot = "1234567890";
google_ad_width = 300;
google_ad_height = 250;
google_color_border = "E32BF1";
google_color_bg = "689BF1";
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>

<div id=”span_ad_04”></div>
<script>
span_ad_04.innerHTML=span_ad_01.innerHTML;
span_ad_01.innerHTML="";
</script>


该种广告投放方式会导致一个广告位对系统产生多次广告查询,浏览器会多次处理这些请求,这样会影响用户体验。为了避免出现该问题,我们建议您按照以下方式修改广告代码:
1. 直接粘贴您的AdSense代码到页面源代码中
2. 通过iframe调用广告代码,但是一个页面只能嵌入一个iframe单元

AdSense 产品部门正在对广告后台进行一些调整以提升广告投放的准确性,如果您在使用类似上述原理的方式投放Google AdSense广告,那么接下来的这些调整可能会影响到您网站的广告投放。我们建议您尽快按照上述符合要求的方式投放AdSense广告,以避免接下来的 调整影响到您网站的AdSense广告投放。

我们注意到大家采用该方式以解决页面内容下载过慢的问题,但是从我们目前的数据和发布商反馈来看,AdSense广告在本地区的投放是不会影响页面内容下载的。

我们会通过系统邮件通知一部分以该方式投放代码的发布商,也希望大家相互转告,尽快实现代码的更换,以避免接下来的产品调整影响您网站的广告展示。如果您对此还有疑问,也欢迎通过支持链接和我们联系。

Tags: google, adsense

PHP框架:Treacle 介绍

群友Bopo自己开发了一个PHP的framework。Bopo从认识到现在,大概也有四五年的时间了吧,不过这个框架的年龄并不是特别长,大概只有2年多左右。最早这个框架BOPO是自己做项目的时候一点点的做的,但后来他终于有想法将它逐步扩大成为了一个框架。

最初看到框架的时候,还是一个雏型,现在,比以前好多了,所提供的支持也多了很多。让我们来看看这个糖浆究竟有些什么。

Treacle 是个什么呢?

Treacle 为开发者轻松、快捷的创建应用程序提供帮助。Treacle 框架简单、清晰,容易理解和学习,并且有完全中文化的文档和丰富的示例程序降低学习成本。

Treacle 有什么特点?

  • 完全跨平台
  • 完全支持 PHP5
  • 不倚赖特别的 PHP 扩展模块
  • 简单、容易理解的 MVC 模型
  • 丰富的助手对象和组件
  • 开放源代码,完全中文化的注释和文档
  • 商业公司提供技术支持

如何获取技术支持?

您可以通过参与我们的论坛来获得技术支持。
官方网址:http://www.treacle.cn/

可能现在有些简陋,但是期待一下吧。

Tags: framework, treacle, bopo

ThinkPHP发布1.5Lite版

一大早流年就在群里说发布了Lite版本,但是我还没有欣赏一下具体的代码,好象这个版本的想法是用Yhustc那里冒出来的,因为他的Yblog就自行对ThinkPHP 1.5进行了简化只保留了常用的功能,比如:数据库只支持MYSQL(也是,这个博客程序只用MYSQL,其他的一些驱动就可有可无了)。于是流年在这个想法的基础上,花了几天时间进行了Lite的构造。(估计几天的休息时间就这么没有了吧)

官方原文:http://www.thinkphp.cn/Blog/25

发布该版本的原因是很多应用开发要求较高的性能并且不需要很多特殊的功能

Lite版本提供网站开发最需要的功能,优化性能,更适合大型项目!

[ 功能列表 ]

编译缓存
自动生成
异常处理
URL模式
语言包支持
模板主题支持
空模块和空操作
前置和后置操作
智能数据表识别
自动加载
标签库
类库导入
Vendor支持
ADSL方法
跨库操作
字段映射
URL组装
URL伪静态
原生SQL操作
多数据库连接和切换
分布式数据库支持
支持MySql和PDO
惯例配置
项目配置
动态配置
模块配置
静态缓存
动态缓存
模板引擎和扩展支持
日志处理
SQL日志
调试模式
运行时间显示
页面Trace
类库扩展
自动验证
自动完成
CURD基本
AR模式基本
连贯操作

[ 注意事项 ]
去掉了ORG类库包(自己可以增加扩展)
保留文件缓存驱动
保留内置模板引擎和PHP模板引擎驱动
查询条件只支持字符串
CURD接口和数据库接口已经更改(和标准版不兼容)
视图模型和关联操作已经去掉
模型的数据操作保留了 add save delete find query execute 增加了select方法 并做了参数的调整
去掉了自动获取数据表字段信息 改由模型自己定义或者不定义
保留运行信息和页面Trace显示
去掉了URL路由功能(该部分功能可以用空模块和空操作取代)

[ 下载Lite版本 ]

Lite版本适合对TP有一定了解的开发人员,并且有PHP开发经验和足够的扩展能力。

Tags: thinkphp, lite

jQuery 1.3 中文文档发布

jquery 1.3刚刚出来没几天,shawphy的中文API就基本出炉了,有时候真的挺佩服他们,当我们在娱乐的时候,他们还在努力的为我们这些人造福。我没有什么其他能力,只能做到代为传播了。同时也是希望有更多的人参与,可以让我们这些使用者也能够更加方便。

网址:http://shawphy.com/2009/01/release-jquery-doc-cn-1-3.html
原文如下:

jQuery 1.3自从2008年1月14日发布后,后引来了各界的关注。我们也随即投入到翻译文档的工作中来。经过4天的努力,终于完工了。这个版本更新了不少东西

changelog:

2009-01-18 16:06:52 +0800
* triggerHandler 进一步说明
* trigger 进一步说明

2009-01-17 22:37:11 +0800
* live() - 与bind()不同的是,live()一次只能绑定一个事件。
* [attribute!=value] jQuery 1.3中意义改变
* load 的data参数在jQuery 1.3中也可以接受String
+ ajax的error回调的第二个参数可能值”timeout”, “error”, “notmodified” 和 “parsererror”
+ ajax参数xhr
* animate 的duration为0的问题
* show, hide, toggle, slideDown, slideUp, slideToggle 在jQuery 1.3中,padding和margin也会有动画,效果更流畅。
* jQuery(html,[ownerDocument])等效于$(document.createElement(”span”)
* is支持复杂表达式

2009-01-17 18:31:10 +0800
+ jQuery.support.scriptEval
+ 原 Dimension 插件功能(1.2.6版加入jQuery核心)

2009-01-16 19:11:10 +0800
+ jQuery.fx.off
+ toggleClass( class, switch )
+ toggle( switch )
+ toggle(speed,[callback])
* 修改queue和dequeue方法的参数和说明

2009-01-15 22:31:02 +0800
* jQuery(html,[ownerDocument])
+ jQuery.selector
+ jQuery.context
* 效果下的queue和dequeue搬到核心下
+ live()
+ die()
+ closest()
* stop( [clearQueue], [gotoEnd]) 增加两个参数
+ jQuery.support
+ jQuery.isArray( obj )

感谢Cloudream的热情帮忙。还要感谢一揪制作chm版。这个版本还加入了检查更新的功能。如果有需要的同学可轻松查看是否有更新的中文文档(chm版中的检查更新也将同步升级)。

在线查看 下载离线版 bug提交

Tags: javascript, jquery, api

Records:44123456789