朱博的技术园

关注基于.Net的Web解决方案,高性能数据库设计,高性能Web服务解决方案

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  14 随笔 :: 0 文章 :: 200 评论 :: 3 引用

2009年6月6日 #

前言

继去年参加了Google Developer Day 2008后,又迎来了Google Developer Day 2009,谢谢公司给我的时间,得以如愿参加这个技术盛宴。

未标题-1

我充分吸取了去年的教训,提前到达位于北京国际会议中心的会场,领到了可以留作纪念的嘉宾牌。

开幕、欢迎辞、开复主题演讲

与去年相同,先有用时一个多小时的概述,再开始各个分会场的课程。与去年不同的是,致开幕词的不再是那位来自美国的美女工程师了,而是谷歌开发技术推广部中国首席经理栾跃,栾跃简洁的开幕词后,是开复的精彩演讲。我注意到中文在这次的GDD的比重加大了很多,我想,这是开复来中国后,Google“本地化” 的另一成果。

nEO_IMG_IMG_5257 nEO_IMG_IMG_5259 nEO_IMG_IMG_5261

开复的演讲我觉得比去年的更精彩,更能提起人的胃口。

nEO_IMG_IMG_5265 nEO_IMG_IMG_5266

技术的发展,往往迅雷不及掩耳。记得去年的GDD,谈到了云计算这个概念,经过了1年的发展,云计算的概念已经深入人心。去年谈到的App Engine、Google Maps API、Open Social、Android、iGoogle、Google Web Toolkit今年都有讲,这些技术都已经得到了更进一步的发展。值得注意的是,去年谈到的Gears,今年只字未提,这是因为今年的新技术:HTML5 其实已经可以替代Gears了。今年的重头戏是Google Wave,我知道最近在美国举行的2009 Google I/O大会上公布的Google Wave引起轰动,据说这是可以媲美Email发明的里程碑式的通讯工具。在开复的演讲里,我也得以亲眼所见,演示到精彩之处,全场情不自禁地响起热烈的掌声,真不是盖的。OK,接下来我就按照开复的演讲顺序,一一记录于此,与大家分享。

Google Maps API

下图是Google 一位工程师演示Google Maps API,他的示范是一个高考地图,可以根据专业、往年分数线、地域等来搜索适合自己的高校,对于本次的高考生填志愿来说,非常方便。Google Maps API今年的新特性加入了我的位置功能(My Location),其原理是根据用户手机所在的基站(Cell Tower)地理位置,或者用户无线上网所使用的热点地理位置来获得用户的位置,对于用过Google 手机地图的用户来说,应该对这项已有体会。

nEO_IMG_IMG_5269

该工程师所做的另一个示例我没有拍下来,是由Google制作的旅游路线规划,现场示范的是台湾旅行路线图,制定好了起点(桃园机场),终点后,Google Maps会自动计算得出旅行路径,用户还可以自定义路行途径点,Google Maps会根据新增的点重新计算路径。并且可以通过网络摄像头看到实时的公路路况,决定自己的出行时间。

接下来是来自兰州大学的一对师生演示的基于Google Maps的“公共危机信息管理”:只要定义了灾害地点,灾害影响范围,可供逃生的地点,系统会自动计算需要疏散的人群,并且可以自动显示疏散路径。我觉得这个系统非常值得推广,拿官话来讲,“对于保护人民的生命财产安全具有重要意义。”

nEO_IMG_IMG_5270

Open Social

接下来是我最感兴趣的Open Social环节,经过1年的发展,Open Social已经到了稳定版0.8.1,最新版0.9。

nEO_IMG_IMG_5271

在0.8.1之前,只能通过JavaScript开发,而之后,可以用任何自己喜欢的语言进行开发,而且还新增了RESTful protocol、RPC protocol。这对于Shindig与AppServer、Shindig与ContainerServer之间的交互提供了更快的,可以在后台运行的数据传输方式(我对RESTful protocol、RPC protocol的理解不是太清楚,如有误,谢谢指出)。

nEO_IMG_IMG_5437

另外,还新增了一个虚拟货币(Virtual Currency)的API,对于需要提供支付功能的应用来说,多了一种开放、稳定的选择。

nEO_IMG_IMG_5442

我觉得最值得称道的是新的OSML Tags(Open Social Markup Language Tags) 与 Templates,以往需要许多行才能实现的界面,现在只需要一个简单的 Tag(如:<os:PeopleSelector>),就可以实现,代码可读性更强,开发更加迅速。

nEO_IMG_IMG_5446 nEO_IMG_IMG_5448

OpenSocial 的使用者去年只有天际和聚友,到了今年,无论是平台提供商还是应用开发商,支持者多了很多。相信到了明年会更多,希望价值中国网能在明年的GDD大会上作为合作伙伴出现。

nEO_IMG_IMG_5273

HTML 5

开复在对iGoogle做了简短的介绍后,就开始了对激动人心的前瞻技术的介绍:HTML 5,O3D,Google Wave。

nEO_IMG_IMG_5278

做过Windows客户端程序的同仁们应该对UI界面的灵活性印象深刻,可以精确到像素来控制各个控件的位置,而且可定制化很高。但基于HTML的Web App UI就没那么自由了。HTML 5 给我们带来了也基于像素级别的控制:Canvas,我们看到下面的图中,有各种非标准的HTML控件,放在HTML4时代,其实现无非就是用图片作为背景来实现,对于用户的实时绘图,其原理是记录用户某次操作的修改路径,传回服务器,由服务器修改图片后再传回给客户端。HTML5的对此的实现却是原生的,无需多余的数据传输。如下面中图里面的鼠标作画,只需要用下面右图的简单代码即可实现。Amazing!Isn’t is?

nEO_IMG_IMG_5283 IMG_5295 IMG_5296

在网页中嵌入视频,在HTML4时代,我们的做法是嵌入各种Object,只有当客户端支持某种视频格式的解码,才能顺利播放。那么在HTML5中,试试新的标签<video id=”v1” src=”test.mov” controls>吧,像插入一张图片一样,插入视频,无需考虑编码,是多么舒畅的感觉!

nEO_IMG_IMG_5284

而HTML的视频特性与Canvas特性相结合,就有了下图中的应用:上面的方框显示的是演示者的视频对话,下面的方框捕捉视频中变化的像素,当演示者摇头时,下面就会实时绘出移动的像素,看上去就像照片里面只把头抠出来一样;如果演示者眨眼,下面就会显示代表眨眼的两个方框,这一切都只是由HTML5 + JS实现的,Amazing!

IMG_5321

HTML5带来的新特性还有地理位置。通过地理位置的特性,我们可以比现有的技术更加方便地制作类似x附近y米的z的应用。

nEO_IMG_IMG_5285

HTML5 还有一个重要的特性就是应用程序缓存和数据库。传统WebApp的一大弊端是如果网络断开,或者网络质量不好,会严重影响WebApp的体验,甚至完全无法运行。而在HTML5中,内建了应用程序缓存和数据库的特性,当网络断开或者质量不好时,可以先在本地的数据库中存储用户提交的数据,待网络连通或质量变好后,再与服务器同步,相信用过Google Docs,并且开启了Offline功能的同仁们会体会深刻。但不同的是现在的Google Docs Offline是基于Gears的,如果浏览器不安装Gears,是没法使用的。我们能想象,如果有一天HTML5被广泛支持,不再需要下载Gears这样的插件就可以轻松开发可以离线的WebApp,是多么值得期待啊。幸运的是目前Chrome、FireFox、Safari、Opera均已支持,只待 IE了。

nEO_IMG_IMG_5286

HTML 5最后一个特性是Web Workers。如果有人写过特耗资源的JS代码,应该体会过等待这段JS代码执行的过程中,当前浏览器什么都不能干的糟糕体验。有了Web Workers,可以让这种很耗资源的JS代码在后台执行,从而不影响用户的操作,现场演示时,工程师在使用了Web Workers的浏览器中,看着非常耗资源的代码在一点一点执行(执行结果实时输出在了屏幕上),他却能非常流畅的进行其他操作,现场响起了非常热烈的掌声。

nEO_IMG_IMG_5287

如果各位注意到了本文第7张图片右侧的讲台颜色的话,那么这里有一个解答,那是五种颜色,分别代表HTML5的五个重要特性。

nEO_IMG_IMG_5288

O3D

接下来是O3D的演示,我们以往的3D应用,比如Second Life,基本上都是客户端的软件,而有了O3D的支持,可以在浏览器中显示界面丰富的交互式3D应用。值得注意的是,浏览器里的3D,主要靠GPU的支持,这样对CPU的压力小了很多。下面我放了一段现场演示的视频,可以看到视频非常漂亮,竟然是在浏览器内部执行的。(Youtube被和谐了,只好传到土豆)

nEO_IMG_IMG_5289

Google Wave

接下来是期待已久的Google Wave了,我将花较大篇幅来介绍,这的确是意义堪比Email的又一项伟大发明。演讲者是来自澳大利亚与来自美国的工程师,之所以要两个人,是因为他们要模拟两个人在使用Google Wave时是如何沟通的。

nEO_IMG_IMG_5331

单次Email(下左图)的沟通是单向的,比如我在给A发邮件时,A只有等我点击发送后,才能收到,我也只有等A收到后见并回复后,才能收到回复。而在 Google Wave(下右图)里,我们看到信息是可以双向流动的,How?Just follow me.

nEO_IMG_IMG_5333 nEO_IMG_IMG_5334

下图中,Dan正在给Adam(白色边框标出)发消息,这个过程和发邮件类似

nEO_IMG_IMG_5337

Adam 收到了Dan 发来的消息,他可以回复给Dan,这里仍然和Email类似,但再接下来,就是Google Wave的“独门功夫”了

nEO_IMG_IMG_5338

我们在收发邮件时,应该遇到过这样的情况:想要针对对方发来的邮件中的某一段内容进行回复,而且对方此时正在线。这是如果还是用Email的话,需要将要回复的内容拷贝下来作为引用,然后给对方回复,对方过大概5分钟(Outlook延时)收到后,再接着回复。如果是Google Wave呢?看下左图,我们可以直接选择要回复的那段文字,直接回复,而且如果对方也在线,可以像IM一样实时聊天。看下右图,他们真的在针对那段文字开聊了。Amazing!此处场内响起来热烈的掌声。

nEO_IMG_IMG_5339 nEO_IMG_IMG_5342

如果我们要给对方发图片怎么办?如果使用Email,需要将图片作为附件发送,对方收到后,一一点击出来看。Google Wave呢?直接将要发的图片拖拽到编辑器里,如下图,点击发送,对方收到的直接可见的图片。

nEO_IMG_IMG_5346

对方也可以直接回复图片,甚至直接对发过来的图片作补充,值得注意的是:在回复时,无需点击回复,对方就实时看到了增加的三张图片;Oops,图片名称全部是无规则的数字,那来改改吧,在改的过程中,对方实时看到图片名称被修改了。

nEO_IMG_IMG_5347

发送过来的图片,还可以Slide Show的方式查看

nEO_IMG_IMG_5348

当然,手机上的Google Wave也可以顺利进行,这样我们就可以做到Anywhere,Anytime与对方沟通了。

nEO_IMG_IMG_5350

如果Google Wave的演示到此为止,我不会讲它堪比Email的发明。接下来我们看潜力无限的Google Wave API!

与BugSystem集成:

nEO_IMG_IMG_5354 nEO_IMG_IMG_5355 nEO_IMG_IMG_5356

协作数独,能想象两人一起玩数独的场景么?对方填的数字,自己实时可以看到。

nEO_IMG_IMG_5358

实时翻译,注意左图与右图的区别,我们能看到翻译是在用户输入的同时同步进行的,比如输入了Hello,下面会实时出现你好,再输入Beijing,下面的翻译变成了你好北京。这是基于Google Wave API开发的Robot,比起现在各式各样的翻译机器人,是不是更棒?此时,场内再次响起了更热烈的掌声!Amazing!

nEO_IMG_IMG_5360 nEO_IMG_IMG_5361

Android

接下来是Android的环节,我只讲一下我印象最深的几个环节吧

如下左图,许斐用手指拨动G1的滑动球,街景会随着她拨动角度的不同,显示不同角度的景象;G1有内置的方向感应器,接下来,如下右图,她把手机交给了摄影师,由摄影师拿着G1转动了360度,结果大屏幕上看到的景象是,G1的Street View也随着转动了360度,当时的感觉,就好象我们透过G1直接亲眼看到了Google美国总部。Amazing!

nEO_IMG_IMG_5378 nEO_IMG_IMG_5379

还有条形码搜索:许斐用G1的一个条形码扫描程序扫描了条形码后,点击“Open Product Search”,可以看到这款产品的信息,可以按照产品价格倒序或正序排列。

nEO_IMG_IMG_5384 nEO_IMG_IMG_5385 nEO_IMG_IMG_5386

主题演讲总结

至此,开复的主题演讲就结束了,下图是他的总结。

nEO_IMG_IMG_5388

Open Social 分会场

下面的分会场,我参加的都是Open Social的课程,去年Open Social的演讲,基本还在普及概念的阶段,今年的课程,就更实践了。

Google 工程师王超的课程:“设计高效可扩展的Open Social 应用”,从Web App 前端优化的方法切入,通过对示范应用Quartermile优化前后的成本分析,逐步引入了Open Social 0.9中可供改进OS应用的特性。整场课程条理清晰,语言贴切,听下来感觉酣畅淋漓。

还有Google工程师孔贵宾的课程:“利用Open Social建立开放平台”,以校内为例子,从人、关系、动态(新鲜事)、AppData、消息、容器(Container)、视图(View)、兼容性测试的各个细节,把利用Open Social建立开放平台的整个过程详细展现了出来。在帮助校内实施OpenSocial 0.8.1的过程中,有不少宝贵的实践经验,非常值得一提,比如实现Shindig的接口,不必所有接口都实现,比如动态(新鲜事),如果原有系统已经有比较完备的系统,则只实现创建新鲜事即可;又如AppData,为了防止Apps滥用,甚至可以不用实现……

最后又听了王超的课程:“Google Friend Connect应用开发”,看到了除了OpenSocial这样的重量级平台外,Friend Connect可以帮助内容性的网站通过简单的Copy & Paste实现社会化。对他举的小黑屋例子印象深刻:如果当时的会议室灯都关了,大家知道屋里有人,但不知道彼此是谁,如果有一盏灯,大家就会看到对方,开始交流。Friend Connect就是这样这样一盏灯。

一天的课程很快就结束了,收获很多,亲身体会了优秀的技术团队所做的创新,这足以弥补午餐菜太少的不足(听有人说拿包涪林榨菜就着米饭都比那么点菜好,汗一个)。难能可贵的是,拿开复的话讲,这里不只是研究室里面的whitepaper,都是实实在在已经实际应用的技术。

互动交流活动

去年我没有参加晚上的互动交流活动,现在回想起来有些可惜,互动交流活动中,我争取了一个上台演讲的机会,还认识了来自腾讯SoSo产品组的王宇(希望没有记错你的名字),王宇本来也是要上台演讲的,可惜收到服务器报警的信息,直接飞奔回去处理情况了,佩服他的敬业。

我排在第31位,等待的过程中有点紧张,一直在思考该怎么讲,最终的构思是从价值中国的实名制,专业化,股权共享的文化竞争力角度来讲,捎带着谈到所利用的Google技术,目的还是借Google的讲台,宣传一下价值中国。

该上台了,我披着价值中国的狼皮,挺起胸膛,抛弃紧张,信步踏上面对数百人的讲台,从谷歌开发技术推广部中国首席经理栾跃的手中接过话筒,道谢后,开始了价值中国的演讲:“我是来自价值中国网的朱博,价值中国网是中国第一家实行全站实名制的网站,我们提倡、且已经具备了诚信、负责的氛围,我们是在文化这个根本因素上,为解决中国经济发展的瓶颈而努力。用到了Google Blog Search Ping,让会员的文章能更快的被搜索到;正在实施OpenSocial。谢谢Google的技术,让我们能更好更快地达成自己的目标。”

演讲完毕后,就遇到了前来交流的Google中国工程师王超与盛科网络(苏州)的CTO古陶,我想中国发展的瓶颈来源于持续了几千年的文化,这应该是大家的共识,无需描述太多。谢谢两位对价值中国网的支持,特别要感谢王超的时间,他帮我解决了不少OpenSocial的疑问。

结尾

至此,Google Developer Day 2009就全部结束了,在回来的路上,我突然想明白了古陶说的话:“Web2.0的盛行是解决现在中国发展的契机”(原话记不清了,大意如此,如有偏差,古兄看见还请指正),技术是固化的思想,思想来源于文化,Web2.0七大原则中的利用集体智慧、合作而非控制,其实蕴含着独立、负责、诚信等文化因素,也正是因此,Web2.0的出现不在中国。反过来说,Web2.0技术在中国的盛行,能否反过来影响思想,思想再反过来改进文化?我想这个可能性是存在的。Open Social就是个例子,平台商,应用开发商,用户三赢的局面越来越多,我们也逐渐变得诚信、负责、独立、合作了。

posted @ 2009-06-06 02:46 朱博 阅读(2545) | 评论 (25)编辑

2009年3月4日 #

我们公司的网站首页、频道首页静态化策略是这样的:

一个服务ServiceA每5分钟会对配置好的网站首页、频道首页源地址分别发起一次请求,然后把请求的数据写入一个Html文档,这个Html文档即静态化的页面。

本来一直工作的很正常,但今天我使用了自定义的500错误页面后出问题了,首页静态页面不定时地呈现出了我自定义的500错误页面,经分析,发现原来没有使用自定义错误页面时,WebResponse的返回结果是一个错误,可以被捕捉到;但使用了自定义错误页面后,WebResponse就把这个错误页面当成了首页的内容了。

接下来就是改进ServiceA了,在获得WebResponse的内容之前先判断返回的HttpStatusCode,只有是200时才返回页面内容,否则返回一个空字符串,附部分代码:

HttpWebRequest wr = (HttpWebRequest)HttpWebRequest.Create(SourceUrl);
wr.Timeout 
= 20000;  // 20秒
HttpWebResponse wResponse = (HttpWebResponse)wr.GetResponse();

if (wResponse.StatusCode == HttpStatusCode.OK)
{
    StreamReader sr 
= new StreamReader(wResponse.GetResponseStream(), System.Text.Encoding.GetEncoding(Encodeing));
    strContent 
= sr.ReadToEnd();
}

在如何获得Http请求的状态代码时颇费一番周折,后来发现WebResponse类是没有 StatusCode 属性的,只有继承于它的HttpWebResponse类才有;另外,HttpWebRequest.GetResponse 返回的类型竟然不是HttpWebResponse,而是WebResponse,难道HttpWebResponse.GetResponse 还会返回非Http的Response?如果有朋友有答案,感谢分享。

posted @ 2009-03-04 18:24 朱博 阅读(118) | 评论 (0)编辑

2009年3月3日 #

使用这个方法有个前提:用户头像的宽或者高最大不能超过x(x = 图片容器宽度 - 图片与容器的边距),这里的例子是参考了校内网首页右侧最近来访的思路:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    
<title>照片纵向对齐示例</title>
    
<style type="text/css">
    #PhotoList 
{ list-style: none; padding: 0; margin: 0; }
    #PhotoList li 
{ float: left; width: 80px; height: 80px; padding: 5px; }
    #PhotoList li span 
{ display: block; width: 55px; height: 55px; padding: 4px 0 0 4px; border: solid 1px #ccc; }
    #PhotoList li span a 
{ display: block; width: 50px; height: 50px; background-position: center center; background-repeat: no-repeat; }
    
</style>
</head>
<body>
    
<h1>照片纵向对齐示例</h1>
    
<ul id="PhotoList">
        
<li><span><href="#" title="Photo" style="background-image: url(http://hd28.xiaonei.com/photos/hd28/20080804/00/51/tiny_8428e107.jpg);"></a></span></li>
        
<li><span><href="#" title="Photo" style="background-image: url(http://hdn601.xnimg.cn/photos/hdn601/20081216/22/30/tiny_WVti_9278a200150.jpg);"></a></span></li>
        
<li><span><href="#" title="Photo" style="background-image: url(http://hd28.xiaonei.com/photos/hd28/20080804/00/51/tiny_8428e107.jpg);"></a></span></li>
        
<li><span><href="#" title="Photo" style="background-image: url(http://hd28.xiaonei.com/photos/hd28/20080804/00/51/tiny_8428e107.jpg);"></a></span></li>
        
<li><span><href="#" title="Photo" style="background-image: url(http://hdn601.xnimg.cn/photos/hdn601/20081216/22/30/tiny_WVti_9278a200150.jpg);"></a></span></li>
    
</ul>
</body>
</html>

 

效果图:

这个方法的好处是用几乎最少的代码实现了不规则头像的纵向居中。


posted @ 2009-03-03 17:42 朱博 阅读(190) | 评论 (0)编辑

2009年3月2日 #

Yahoo!, Live & Google 支持一个新的标签:"canonical url tag",来帮助网站管理员确定自己创建的重复内容。

如何操作

 这个标签被<head>标签包含,和<meta>标签的区域是一致的。这并不是一个新的标签,和nofollow一样,只是具有一个新的rel参数。如:

<link rel="canonical" href="http://www.seomoz.org/blog" />


 这个标签的意思是当前页面是 http://www.seomoz.org/blog 的一个拷贝,有几种情况可以利用这个标签:

1、通过不同参数来显示相同内容的不同样式,如:http://www.seomoz.org/blog?color=blue

2、通过不同参数来显示相同内容的不同版本,如:http://www.seomoz.org/blog?printversion

3、通过不同参数来显示相同内容的不同SESSION,如:http://www.seomoz.org/blog?SessionID=xxxxxx

当然使用这个"canonical url tag"不只上面的几种情况,具体情况可以具体对待。

搜索引擎提供的一些资料

Google

  • 问:我可以使用相对路径指定canonical么?
    答:可以。
  • 问:canonical指定的页面内容可以与当前页面内容不同么?
    答:我们允许轻微的不同,如排列在表格中的产品数据。而且我们的爬虫也可能在不同时间去抓取canonical与当前的页面,爬虫可能会看到不同的内容版本,这些都是允许的。
  • 问:如果canonical指定的页面不存在会怎样?
    答:我们会继续索引你的内容,但强烈建议用存在的页面作为canonical的内容。
  • 问:canonical可以是一个重定向页面么?
    答:可以。

Yahoo

  • canonical可以是绝对或相对路径,但我们强烈建议使用绝对路径来避免一些不可预知的问题。
  • canonical指定的URL只能与当前页面处于同一个域,如test.example.com的canonical可以是www.example.com,但不能是www.yahoo.com 
  • A作为B的canonical,B作为C的canonical时,Yahoo会把A当作B、C的canonical。但会中断无限的canonical链。

基于ASP.NET的示例代码

using System;
using System.Web.UI;
using System.Web.UI.HtmlControls;

public partial class Products : Page
{
    
protected void Page_Load(object sender, EventArgs e)
    
{
        HtmlLink canonicalTag 
= new HtmlLink();
        canonicalTag.Href 
= "http://www.seomoz.org/blog";
        canonicalTag.Attributes[
"rel"= "canonical";
        Page.Header.Controls.Add(canonicalTag);
    }

}

参考

 

posted @ 2009-03-02 10:45 朱博 阅读(126) | 评论 (2)编辑

2009年1月7日 #

今天被一个简单的问题难住了,先上代码:

Convert.ToDecimal("23.34");

各位猜结果是什么?应该是23.34,但实际我的结果是:2334。

后来输出了CurrentCulture看了一下:竟然是:ca-ES;

再后来在此类的构造函数加了如下代码:

Thread.CurrentThread.CurrentCulture = new CultureInfo("zh-CN");

问题解决。

问题是:

为什么CurrentCulture会是ca-ES?我操作系统是英文版2003,系统的区域设置是中国。

谢谢 eaglet 同志的提醒,做了个实验:

  • 我将 Regional and Language options > Standards and formats(以下简称RAL_SAF) 修改为 English(United States)
  • 任何一个 Windows Console(以下简称Consolse)输出的 CurrentCulture 都为 en-US,与 RAL_SAF 中的配置一致
  • 任何一个 Windows Service(以下简称Service)输出的 CurrentCulture 都仍为 ca-ES
  • 再后来,我试着修改 Regional and Language options > Advanced > Default user account settings 为选中,确定后,再次运行 Service,输出就变成了 en-US
  • 再将 RAL_SAF 改回 Chinese(PRC),运行Service,CurrentCulture 结果仍然是 en-US
  • 再将 Regional and Language options > Advanced > Default user account settings 取消选中、再选中,运行 Service,结果为 zh-CN

得出结论:

  1. Windows Console 的 CurrentCulture 随着 Regional and Language options > Standards and formats 的改变而实时改变;
  2. Windows Service 在未将 Regional and Language options > Advanced > Default user account settings 选中时,CurrentCulture值有可能与 Regional and Language options > Standards and formats 的配置不同
  3. 为了每次修改 Regional and Language options > Standards and formats实时生效,需要将Regional and Language options > Advanced > Default user account settings重新选中并确定

忽然想起来自己的系统第一次安装时,可能因为鼠标滚轮的问题,本来 RAL_SAF 要选择 Chinese(PRC),结果误选为 Catalan(加泰罗尼亚),所以又做了一个测试:将 RAL_SAF 改为 Catalan,Regional and Language options > Advanced > Default user account settings 重新选中并确定,运行Service,输出结果为 ca-ES。

至此,该问题的原因、解决方案都有了。

posted @ 2009-01-07 16:39 朱博 阅读(140) | 评论 (1)编辑

2008年11月14日 #

Tengs2000的文章:《[ASP.NET 优化] IIS6 Gzip》已经图文并茂地把如何在IIS6.0上启用Gzip讲的很清楚了,我这里只是要根据自己在配置过程中的问题做一些补充。

先说说我遇到的问题:我们公司用了CDN服务,在按照上面的方法配置好Gzip后,不通过CDN,直接用Fidller或者FireFox Firebug看页面信息,都能看到已经通过Gzip压缩过了,但是在Linux下面使用wget、curl等 工具查看同样的页面信息时,却发现没有压缩。这个问题一直没有解决。最后在MetaBase.xml第三段IIsCompressionSchemes中发现了三个很重要的参数:

  • HcNoCompressionForHttp10
  • HcNoCompressionForProxies
  • HcNoCompressionForRange

它们的默认值分别是:

  • HcNoCompressionForHttp10="TRUE"
  • HcNoCompressionForProxies="TRUE"
  • HcNoCompressionForRange="FALSE" 

当把HcNoCompressionForHttp10的值设置成FALSE时,wget与curl就可以看到页面已经被gzip压缩了。

由此分析:虽然wget与curl在页面返回信息中写着其使用了http1.1,但实际上它们实际仍然在使用http1.0。禁止为http1.0启用压缩设为否,就可以解决这个问题了。

posted @ 2008-11-14 17:10 朱博 阅读(245) | 评论 (0)编辑

2008年10月21日 #

前言

FCKeditor是使用非常广泛的HTML编辑器,本文从 ASP.NET 的使用场景对 FCKeditor 与 FCKeditor.NET 的配置、功能扩展(如自定义文件上传子目录自定义文件名上传图片的后期处理等)、以及安全性进行初步的阐述。

希望能帮助有同样需求的同仁节省一点时间;也希望各位能指正其中的不足。谢谢。

 

一、自定义 FCKeditor 的 BasePath

BasePath 即FCKeditor在网站中的相对路径,默认值是 /fckeditor/,最好在Web.config appSettings中对其进行配置:

<add key="FCKeditor:BasePath" value="/FCKeditor_2.6.3/"/>


这样做有诸多优点:

  1. 开发环境与生产环境不同,开发环境一般是http://localhost/xxx.com/这种情况下FCKeditor就得放在一个虚拟目录http://localhost/fckeditor/中,若涉及多个网站的开发,而各网站的FCKeditor有差别时,这样显然不是最优;
    而且因为物理目录结构与逻辑目录结构不同,也会有发生错误的隐患;
    而如果采用Web.config的配置,就可以在开发环境采用不同的配置,FCKeditor的物理路径与生产环境保持一致;
  2. 当升级FCKeditor时,只需要将新版本的FCKeditor放在相应版本号的目录里,修改一下配置即可。这样可以解决因为静态资源的客户端缓存问题,不同用户出现不同的错误的问题;
  3. 可以直观地看到自己的FCKeditor的版本号。


二、配置文件上传的目录

FCKeditor的文件上传(如图片上传)目录可以通过Web.config appSettings进行配置,如:

<add key="FCKeditor:UserFilesPath" value="/UploadFile/FCKeditor/"/>


也可以在 /FCKeditorBasePath/editor/filemanager/connectors/aspx/config.ascx 中进行配置,但我建议 FCKeditor 目录中的内容能不改就不改(fckconfig.js除外),这样日后升级可以放心地替换即可。


三、自定义文件上传的子目录的格式

我们知道,一个文件夹下面不能存放过多的文件(据称Windows下面的目录下2000为阈值),否则对该目录的访问会严重影响I/O性能。而FCKeditor的文件存储是在单一的一个目录进行的。我对FCKeditor进行了扩展,可以在Web.config appSettings对存储目录的格式自定义,如:

<add key="FCKeditor:FolderPattern" value="%y/%m-%d/"/>


========================================
以今天的日期为例:这样产生的文件上传子目录格式为:2008/10-21/。
年月日格式的目录可以随意组合,如:

<add key="FCKeditor:FolderPattern" value="%y/%m/%d/"/>

这样产生的文件上传子目录变成了2008/10/21/

========================================
还可以针对不同登录的用户,采用不同的上传子目录
Web.config 修改上传子目录的配置,增加%u表示不同用户使用基于其标识不同的上传子目录

<add key="FCKeditor:FolderPattern" value="%u/%y/%m/%d/"/>

FCKeditor_2.6.3\editor\filemanager\connectors\aspx\config.ascx 中增加获取当前登录用户标识的逻辑

public override void SetConfig()
{
#region Bochuh's Modification
// Identifier for logined user
// Leave blank for default user upload folder
LoginedUserIdentifier = "44";
// 这里替换成获取当前登录用户表示的代码
#endregion

//
……此文件中原来的代码
}

这样可以对不同用户,根据其登录后的标识(一般是用户ID),来使用不同的目录进行存储,如:7394/2008/10/21/(7394是当前登录用户的ID)

 

参考:

  • %u   代表 当前登录用户的标识
  • %y    代表 当前时间的年份
  • %m    代表 当前时间的月份
  • %d    代表 当前时间的日


四、自定义文件上传的文件名格式

FCKeditor对文件名的处理规则是:如果当前目录下没有重名文件,则上传后的文件名与用户PC上的文件名一致;若存在n个重名文件,则加入用户PC上的文件名是Example.xxx,上传后的文件名变为:Example(n).xxx

我的项目里要求对用户上传的文件名变成Guid的格式,所以我对FCKeditor也做了扩展,在Web.config appSettings可以对上传后文件的格式自定义,如:

 

<add key="FCKeditor:FilenamePattern" value="%guid.%extl"/>


这样的文件名如:a299e63a-7d2d-493d-bbb9-99162ef5b6b8.gif

参考:

  • %guid    代表 一个新的guid字符串
  • %fnl    代表 源文件名的小写
  • %fnu    代表 源文件名的大写
  • %extl    代表 源文件扩展名的小写
  • %extu    代表 源文件扩展名的大写


五、对上传图片进行缩放处理

用到FCKeditor图片上传功能的场景中,很多是内容的发表。内容中往往不需要几千像素大小的图片,比如我的项目中,文章区域最宽也就560像素,所以我做了一个扩展,在Web.config appSettings中可以对图片的最大宽度进行自定义:

<add key="FCKeditor:MaxWidthOfUploadedImg" value="560"/>


有了这段配置,上传后的图片的宽度都控制在了560像素及以内


六、自定义上传后图片URL中的域名

为了加快页面的渲染,我们可以把图片等静态资源放在一个独立的域名当中。但FCKeditor默认的图片上传后URL是相对路径,如图:

我增加了这个扩展,在Web.config appSettings可以配置上传后图片URL的域名,如:

<add key="FCKeditor:UploadedFilesDomain" value="http://a.cvimg.cn/"/>

 

如图:

 


七、解决上传文件名含有中文的文件时提示 "invalid file type" 的问题

这个问题只需要在Web.config中增加一段配置即可解决:

<location path="FCKeditor_2.6.3/editor/filemanager/connectors/aspx/upload.aspx">
    
<system.web>
        
<globalization requestEncoding="utf-8" responseEncoding="gb2312"/>
    
</system.web>
</location>


注意:

  1. responseEncoding是网站的默认编码
  2. FCKeditor_2.6.3是FCKeditor的BasePath


八、FCKeditor的安全性

在FCKeditor的2.3.2版本里,曾有一个漏洞,可以通过 /editor/filemanager/browser/default/connectors/aspx/connector.aspx 往服务器上传任意文件,我的网站就曾经中招。

2.6.3虽然暂未发现类似的问题,但一般情况下用不到的文件最好还是删除比较好:

  1. FCKeditor BasePath 根目录中除了保留:
    1. /editor
    2. /fckconfig.js
    3. /fckpackager.xml
    4. /fckstyles.xml
    5. /fcktemplates.xml
    6. /license.txt
    外,全部删除
  2. /editor/filemanager/中除了保留:
    1. /connectors/aspx/config.ascx
    2. /connectors/aspx/upload.aspx
    外,全部删除
  3. 删除 /editor/_source/
  4. /editor/filemanager/connectors/aspx/config.ascx 的 CheckAuthentication() 方法中,增加验证用户是否登录的逻辑

注意:以上措施仅适用于ASP.NET的网站,其他语言版本的网站未考虑。

附:基于FCKeditor.Net_2.6.3修改后的源码

SOURCE: http://files.cnblogs.com/zhubo/FCKeditor.Net_2.6.3_20081111.rar
BIN(.NET 2.0): http://files.cnblogs.com/zhubo/FredCK.FCKeditorV2_20081111.rar

  1. 对以下文件的指定行进行了修改,
    /FileBrowser/Config.cs  line 45, 116, 169
    /FileBrowser/FileWorkerBase.cs  line 68, 98, 110, 125, 278
  2. 所有修改的地方均包含在名为 "ZhuBo's Modification" 的代码块中,也可以通过搜索整个项目中的 "ZhuBo's Modification" 快速看到改动的地方,方便自己的扩展(比如可以设定图片的最大高度)

更新 at 2008-11-11

新增可选的根据用户标识让不同用户使用独自的图片上传子目录,参见上文中“三、自定义文件上传的子目录的格式”的更新部分。

新的源码与dll文件也已更新。

posted @ 2008-10-21 15:52 朱博 阅读(3108) | 评论 (63)编辑

查看搜狐博客的列表页面的源代码会发现,列表的内容在源代码里面不存在,搜狐博客是通过AJAX的方式动态加载日志列表的。以 http://zouhengfu.blog.sohu.com/entry/ 为样本来进行分析:

日志的列表与分页分别会在下面的代码里:

1<div id="entryList">
2   <div style="line-height:100px;">正在加载日志数据</div>
3</div>
4<div class="item-info">
5   <div id="pageText"></div>
6</div>


FireBug的分析,发现实际的日志列表内容是由:http://zouhengfu.blog.sohu.com/action/v_frag-ebi_c223f68792-pg_2/entry/ 提供的

在这个URL中,从左到右:

zouhengfu 不具有标识作用,替换成www一样可以
c223f68792 由源代码中var _ebi = 'c223f68792'执行escape而得到:
var url='/action/v_frag-ebi_'+escape(_ebi); //common.v.081016.js
-pg_2 页码,2代表第二页,可以把此项去掉获得第一页内容

在做搜狐博客抓取时可以参考。

posted @ 2008-10-21 11:52 朱博 阅读(450) | 评论 (3)编辑

2008年10月14日 #

引言

“公司网站的一次改版后,大批用户反映看到的页面出现错乱的情况,也有不少用户表示他们对这次的改版非常满意。不同的用户竟然看到了不同的效果……”

上面的情形,相信不少同仁都遇到过,在不同PC上看到的网页效果不同。怎么解决这样的问题呢?这就需要做好静态资源的版本控制。

原理

我们先来分析一下出现这个问题的原因:

用户在浏览器浏览某个网页,浏览器在加载网页中包含的各个资源(JS、css、图片)时,先会判断缓存中是否已经包含了此资源(当然这与Header中定义的Cache-Control有关,静态资源很少有设置成不缓存的,我这里默认它们都是可缓存),如果包含,就不去服务器获取了。

比如改版时更改了样式表:Global.css,浏览过网站的用户,缓存里面还存在着Global.css,所以浏览器会“自作聪明”地使用缓存中的版本,自然看到的和我们期望的效果不一样了。

解决方案

如果要让浏览器的缓存更新,就需要改变此资源的URL (统一资源定位符 Uniform Resource Locator)。改变URL不意味着文件需要改名,只需要在文件名后面增加一个后缀,比如:“Global.css?v=yyyyMMddv”,虽然定位到的资源仍然是Global.css,但如果v的值不同,浏览器会认为是不同的资源。同理,对于JS、图片来说,也是如此。

也就是说,我们每次对静态资源有更改,只需对其URL做相应更改,所有的用户就能够获取到最新的资源。

我们再来分析一下这个URL:
Global.css?v=yyyyMMddv
Global.css 资源的位置
v 可随意定义,这里的v代表“version”
yyyyMMddv 可随意定义,这里用“年 + 月 + 日 + 当天修订版本”,这样的URL可读性比较强。也有用随机字符串代表的

新的问题

在解决了上述问题后,我们可能又会遇到新的难题:如果某个CSS或者JS被上百个页面所引用,每个引用的URL又不尽相同,结果是用户看到的同样的样式定义,在页面A和页面B的效果是不一样的。如何能统一,又能有效控制所有页面引用资源的URL呢?

改进后的解决方案

本文标题是:“ASP.NET Web 开发……”,那我们这里就看一下ASP.NET的方法:

定义一个用户控件:CssGlobal.aspx:

1<link rel="stylesheet" type="text/css" href="http://demo.com/CSS/Global.css?v=yyyyMMddv" />

在所有需要引用Global.css的页面上,使用该控件替代传统的引用:
1<%@ Register Src="~/CssGlobal.aspx" TagName="CssGlobal" TagPrefix="uc1" %>
2
3<head runat="server">
4    <title>Title</title>
5    <uc1:CssGlobal ID="CssGlobal1" runat="server" />
6</head>

以后凡是有Global.css的更改,只需要修改用户控件CssGlobal.aspx中Global.css的URL即可

对于JS、图片等其他静态资源,我们也可以用同样的方法实现良好的版本控制

本方案的缺点

1、无法在“设计”视图里看到实时的效果。不过如果美工与程序分离的不错的情况下,相信这不是大的问题;

2、在静态页面,比如.html或者.htm等无法使用用户控件的页面里,没有更好的办法。

在此抛砖引玉,期待各位同仁更好的解决方案。

更新:

2008-10-14 23:42 | 12楼 chunchun的方案

对于aspx页面不需要走用户控件,aspx支持SSI命令,直接写一个CssGlobal.inc文件,文件内容:<link rel="stylesheet" type="text/css" href="http://demo.com/CSS/Global.css?v=yyyyMMddv" />

在需要引用该CSS的页面的位置<!--#include file="CssGlobal.inc"-->

最终生成的页面是经过Ssinc.dll解析的,只会看到<link rel........不会看到<!--#include ......

对于静态页面,CV文章生成页面可以生成shtml文件(或.stm、.shtm )不生成.html这样在页面中都可以用<!--#include file="CssGlobal.inc"-->

改版时要更改样式的版本号只需修改CssGlobal.inc这一个文件即可,动,静态页面都跟着改变。

对于象logo图片这种百年不变的东西 可以象baidu的节日logo那样设一个N长的客服端缓存,客户端第一次加载完了后基本在他重装系统或清浏览器缓存之前都不会到服务器下载,节省很多带宽。 换logo图片时修改的图片名。

posted @ 2008-10-14 15:58 朱博 阅读(2077) | 评论 (19)编辑

2008年9月24日 #

“对这些重要文件*注1的修改将立即被ASP.NET运行库检测到,并导致所有页面被重新编译。”

——《精通ASP.NET程序设计 Programming Microsoft ASP.NET》第12章

如上面所述,我们在修改配置文件Web.config时,因为所有页面都会重新编译,会导致短暂的服务中断。这里有一个方法可以避免:

 

将常用且有可能发生改变的配置都放在appSetting节中,如:

<appSettings>
    
<add key="SMTPServerAddress" value="0.0.0.0"/>
</appSettings>


Web.config中appSettings节有个属性:configSource,这个属性可以指定一个存储appSettings的外部文件路径(只支持相对路径),而这个外部文件的修改是不会引起页面的重新编译的,同时它的改动也能立即被ASP.NET运行库检测到。可谓一举两得。

Web.config中的appSettings的配置:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    
<appSettings configSource="Settings\WebAppSettings.config" />
</configuration>


外部文件Settings\WebAppSettings.config的内容:

<?xml version="1.0" encoding="utf-8"?>
<appSettings>
    
<add key="SMTPServerAddress" value="0.0.0.0"/>
</appSettings>

 

*注1、Web.config配置文件

posted @ 2008-09-24 11:49 朱博 阅读(464) | 评论 (2)编辑