分类 Web 下的文章

使用Ajax来实现Streaming模式的Comet

Firefox和Safari浏览器中,XMLHTTPRequest支持interactive readyState的状态


其对应的readyState状态为3,当Client接收到Server端的一部分数据后就可以触发该状态


当Request请求完成后同样还会触发Success的状态


于是,可以利用这个特性来实现Streaming模式的Comet


Client端测试代码如下:



折叠复制代码




  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

  2. <htmlxmlns="http://www.w3.org/1999/xhtml">

  3. <head>

  4. <title>Comet demo</title>

  5. <metahttp-equiv="Content-Type"content="text/html; charset=utf-8"/>

  6. <scripttype="text/javascript"src="prototype.js"></script>

  7. </head>

  8. <body>

  9. <divid="abc">The server time will be shown here</div>

  10. <scripttype="text/javascript">

  11. var _url="ajax_polling_server.jsp";

  12. var options= {

  13. method:'get',

  14. parameters:'t=0&callback=cb',

  15. onInteractive:ajaxCallBack,

  16. onComplete:ajaxCompletCallBack

  17. };

  18. var ajax=newAjax.Request(_url, options);

  19. var byteoffset=0;

  20. function ajaxCallBack(transport)

  21. {

  22. var ret=transport.responseText;

  23. var data=ret.substring(byteoffset);

  24. byteoffset=ret.length;

  25. $('abc').innerHTML=data;

  26. }

  27. function ajaxCompletCallBack(transport)

  28. {

  29. $('abc').innerHTML=transport.responseText;

  30. }

  31. </script>

  32. </body>

  33. </html>




Server端代码如下:



折叠复制代码




  1. <%@ pagelanguage="java"contentType="text/html;charset=UTF-8"

  2. pageEncoding="UTF-8"%>

  3. <%@pageimport="java.util.Date"%>

  4. <%

  5. response.setHeader("Cache-Control", "no-store");

  6. response.setHeader("Pragma", "no-cache");

  7. response.setDateHeader("Expires", 0);

  8. out.flush();

  9. %>

  10. <%


  11. for(int i=0; i<10; i++){

  12. out.print(new Date());

  13. out.flush();

  14. Thread.sleep(1000);

  15. }

  16. %>





注意:



  1. 该特性目前只适用于Firefox和Safari

  2. 注意Client代码中的byteoffset,利用这个偏移量来获取每次返回结果中最新的部分


 

使用Iframe来实现Streaming模式的Comet

要实现一个基于Streaming模式的comet,比较通用的办法就是使用Iframe来实现


但iframe有一个比较大的问题,浏览器中的进度条会一直停留在某个地方,显示正在加载


Google的工程师们,包装了一个js对象,在IE下使用htmlfile,Firefox下嵌套Iframe解决了这个问题


测试代码如下,Client端页面代码:



折叠复制代码




  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

  2. <htmlxmlns="http://www.w3.org/1999/xhtml">

  3. <head>

  4. <title>Comet demo</title>

  5. <metahttp-equiv="Content-Type"content="text/html; charset=utf-8"/>

  6. <scripttype="text/javascript"src="prototype.js"></script>

  7. </head>

  8. <body>

  9. <divid="abc">The server time will be shown here</div>

  10. <scripttype="text/javascript">

  11. var comet= {

  12. connection : false,

  13. iframediv : false,

  14. initialize: function() {

  15. var userAgent=navigator.userAgent.toLowerCase();

  16. if (/msie/.test(userAgent) && !/opera/.test(userAgent)) {

  17. // For IE browsers

  18. comet.connection=newActiveXObject("htmlfile");

  19. comet.connection.open();

  20. comet.connection.write("<html>");

  21. comet.connection.write("<script>document.domain='"+document.domain+"';</script>");

  22. comet.connection.write("</html>");

  23. comet.connection.close();

  24. cometcomet.iframediv= comet.connection.createElement("div");

  25. comet.connection.appendChild(comet.iframediv);

  26. cometcomet.connection.parentWindow.comet= comet;

  27. comet.iframediv.innerHTML="<iframe id='comet_iframe' src='./ysz_1.jsp'></iframe>";

  28. }


  29. if( /mozilla/.test(userAgent) && !/(compatible|webkit)/.test(userAgent) ) {

  30. // For Firefox browser

  31. comet.connection=document.createElement('iframe');

  32. comet.connection.setAttribute('id','comet_iframe');

  33. with (comet.connection.style) {

  34. left=top= "-100px";

  35. height=width= "1px";

  36. visibility="hidden";

  37. display='none';

  38. }

  39. comet.iframediv pan>=document.createElement('iframe');

  40. comet.iframediv.setAttribute('src', './ysz_1.jsp');

  41. comet.connection.appendChild(comet.iframediv);

  42. document.body.appendChild(comet.connection);

  43. }


  44. if (/webkit/.test(userAgent) || /opera/.test(userAgent)) {

  45. // for other browsers

  46. comet.connection=document.createElement('iframe');

  47. comet.connection.setAttribute('id', 'comet_iframe');

  48. comet.connection.setAttribute('src', './ysz_1.jsp');

  49. with (comet.connection.style) {

  50. position="absolute";

  51. left=top= "-100px";

  52. height=width= "1px";

  53. visibility="hidden";

  54. }

  55. document.body.appendChild(comet.connection);

  56. }

  57. },


  58. // this function will be called from backend.jsp

  59. printServerTime: function (time) {

  60. $('abc').innerHTML=time;

  61. },


  62. onUnload: function() {

  63. if (comet.connection) {

  64. comet.connection=false; // release the iframe to prevent problems with IE when reloading the page

  65. }

  66. }

  67. }

  68. Event.observe(window,'load',comet.initialize);

  69. Event.observe(window, 'unload', comet.onUnload);

  70. </script>

  71. </body>

  72. </html>




Server端jsp代码:



折叠复制代码




  1. <%@ pagelanguage="java"contentType="text/html;charset=UTF-8"

  2. pageEncoding="UTF-8"%>

  3. <%@pageimport="java.util.Date"%>

  4. <%

  5. response.setHeader("Cache-Control", "no-store");

  6. response.setHeader("Pragma", "no-cache");

  7. response.setDateHeader("Expires", 0);

  8. out.flush();

  9. %>

  10. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

  11. <htmlxmlns="http://www.w3.org/1999/xhtml">

  12. <head>

  13. <title>Comet backend</title>

  14. <metahttp-equiv="Content-Type"content="text/html; charset=UTF-8"/>

  15. </head>

  16. <body>


  17. <scripttype n>="text/javascript">

  18. // KHTML browser don't share javascripts between iframes

  19. var is_khtml=navigator.appName.match("Konqueror") || navigator.appVersion.match("KHTML");

  20. if (is_khtml)

  21. {

  22. var prototypejs=document.createElement('script');

  23. prototypejs.setAttribute('type','text/javascript');

  24. prototypejs.setAttribute('src','prototype.js');

  25. var head=document.getElementsByTagName('head');

  26. head[0].appendChild(prototypejs);

  27. }

  28. // load the comet object

  29. //alert(window.parent.comet)

  30. var comet=window.parent.comet;

  31. </script>

  32. <%


  33. for(int i=0; i<10; i++){

  34. out.println("<scripttype='text/javascript'>");

  35. out.println("comet.printServerTime('" + (new Date()) + "');");

  36. out.println("</script>");

  37. out.flush();

  38. Thread.sleep(1000);

  39. }

  40. %>


  41. </body>

  42. </html>




以上代码,在Tomcat里测试正常,可以看到页面内容在不断变化,但如果用nginx反向代理后,页面就不能实时变化,而是最后load完了才变化


查了好久原因,才发现,nginx的proxy默认会Buffer后端Server的响应内容,导致Client端不能实时更新,解决很简单,把buffer给关闭就可以了:



折叠复制代码




  1. proxy_buffering off;




但在Resin里面,上述代码仍旧没有测试通过,页面无法实时更新,暂时还没有找到原因


但Resin自己也提供了一套comet的解决方案,参见这里


 

Web应用中的Comet技术

Web开发中,Comet通常是指在Client和Server端维持一个长连接


当有新消息到达时,Server端可以实时把消息push到Client端


实际上,要实现“服务器推送”,不一定非要用基于http的comet来做


还可以基于socket来实现,比如:flash、applet、html5等


可以参考IBM的“Comet:基于 HTTP 长连接的“服务器推”技术


就Comet的实现来说,可以有两种方式:


1. Streaming流模式:这种方式,实际上才是真正的长连接,Client和Server端一直维持该连接


当Server端有数据时,立即把数据返回给Client,Client马上去解释处理该数据


然后该连接继续保持,等待后续的数据....


2. Long Polling长轮询模式:当Server端没有数据时,该连接一直保持着,当返回给Client端后,Server端就断掉该连接


同时,Client端再发起一个新的长连接,依次循环...


从具体的技术实现上,comet可以有以下方式:


1. Iframe,可适用于Streaming和Long Pooling这2种模式,返回的数据格式使用Chunked来进行传输,使用它最大的缺点是,浏览器上可能会有进度条或不停Loading,不过,总还是有解决办法 的,见这里


2. Ajax, 可以适用于任何浏览器的Long Pooling模式。对于Streaming模式,在Firefox和Safari下可以使用,参见这里


3. Jsonp, 只适用于Long Pooling模式,它的好处是可以跨域,但同样会有浏览器不断Loading的问题

Sohu邮箱上线全程https功能

今日,Sohu邮箱上线了“全程Https”的功能


mail.sohu.com的证书早就申请下来了


其实,技术要做的主要工作是:


如何不让浏览器弹出“不安全”的警告框


由于邮箱中有很多iframe,同时还有很多广告碎片等元素


所以,大部分时间都花在了整理前端的js


同时,修改后台的代码,过滤外域src资源并提供前端所需要的URL


以下是几个要点:



  1. 对于请求mail.sohu.com之外的资源,如CDN上的图片等,使用了反向代理,并在nginx层增加Cache(如果没有Cache,nginx端外域代理并发大时,可能会返回403错误...),参见:配置nginx的cache

  2. 遍历所有的iframe,把src中直接document.write的地方修改为具体的页面,如blank.html,参见:https下的iframe

  3. 对于一些图片广告资源,使用类似//mail.sohu.com/....或/static/images/...的方式,来自适应http和https的访问,参见:web页面中自动切换http/https

  4. 一些浏览器(如:IE)会自动缓存https下的Get请求,只好在url后面加上随机数来防止缓存了


 

实现一个简单的Gmail contextual gadget

关于Gmail contextual gadget是什么,可以参考这里

 

简单的说,Gmail contextual gadget是一个能在Gmail里触发的gadget

 

邮件的Subject,Body,From,To...等包含某个指定的文本或者link时,均可以触发改gadget

 

实现一个Gmail contextual gadget还算比较简单,我们只需要实现Manifest和Gadget.xml即可

 

以下是一个简单的Manifest文件,使用了google.com:HttpLinkExtractor,在Subject和Body中查找满足条件的链接

 


折叠复制代码




































































  1. <?xmlversion="1.0"encoding="UTF-8"?>
  2. <ApplicationManifestxmlns="http://schemas.google.com/ApplicationManifest/2009">
  3.  
  4. <!-- Support info to show in the marketplace & control panel -->
  5. <Support>
  6.  
  7. <!-- URL for application setup as an optional redirect during the install
  8. <Linkrel="setup"href="http://www.tech126.com/gadgets/setup.php?domain=${DOMAIN_NAME}"/>
  9. -->
  10.  
  11. <!-- URL for application configuration, accessed from the app settings page in the control panel
  12. <Linkrel="manage"href="http://www.tech126.com/gadgets/admin.php?domain=${DOMAIN_NAME}"/>
  13. -->
  14.  
  15. <!-- URL explaining how customers get support. -->
  16. <Linkrel="support"href="http://u.sohu.com/help/help1_free.jsp"/>
  17.  
  18. <!-- URL that is displayed to admins during the deletion process, to specify policies such as data retention, how to claim accounts, etc. -->
  19. <!--<Link rel="deletion-policy" href="http://www.tech126.com/google/deletion-policy.php" />-->
  20. </Support>
  21.  
  22. <!-- Name and description pulled from message bundles -->
  23. <Name>Sohu Mail UFile</Name>
  24. <Description>A sohu mail ufile info for Gmail contextual gadgets</Description>
  25.  
  26. <!-- Show this link in Google's universal navigation for all users -->
  27. <Extensionid="navLink"type="link">
  28. <Name>Sohu Mail UFile</Name>
  29. <Url>http://u.sohu.com?from=google&domain=${DOMAIN_NAME}</Url>
  30. </Extension>
  31.  
  32. <!-- Declare our OpenID realm so our app is white listed -->
  33. <Extensionid="realm"type="openIdRealm">
  34. <Url>http://u.sohu.com</Url>
  35. </Extension>
  36.  
  37. <!-- EXTRACTOR -->
  38.   ;
  39. <Extensionid="UFileIdExtractor"type="contextExtractor">
  40. <Name>UFileId</Name>
  41. <Url>google.com:HttpLinkExtractor</Url>
  42. <Paramname="url"value=".*u.sohu.com/download/(d+)/(d+)$"/>
  43. <Triggersref="UFileIdGadget"/>
  44. <Scoperef="emailSubject"/>
  45. <Scoperef="emailBody"/>
  46. <Containername="mail"/>
  47. </Extension>
  48.  
  49. <!-- GADGET -->
  50.  
  51. <Extensionid="UFileIdGadget"type="gadget">
  52. <Name>Sohu Mail UFile contextual gadget</Name>
  53. <Url>http://www.tech126.com/gadgets/sohu_mail_ufile_gadget.xml</Url>
  54. <Containername="mail"/>
  55. </Extension>
  56.  
  57. <!-- SCOPE -->
  58.  
  59. <Scopeid="emailSubject">
  60. <Url>tag:google.com,2010:auth/contextual/extractor/SUBJECT</Url>
  61. <Reason>This application searches the Subject: line of each email for the link "http://u.sohu.com/download".</Reason>
  62. </Scope>
  63.  
  64. <Scopeid="emailBody">
  65. <Url>tag:google.com,2010:auth/contextual/extractor/BODY</Url>
  66. <Reason>This application searches the message body of each email for the link "http://u.sohu.com/download".</Reason>
  67. </Scope>
  68.  
  69. </ApplicationManifest>


 

然后,再调用指定服务器上的gadget.xml去执行相应的操作

 


折叠复制代码





























































  1. <?xmlversion="1.0"encoding="UTF-8"?>
  2. <Module>
  3. <ModuleP refstitle="Sohu Mail UFile Link"
  4. description="The File information"
  5. height="20"
  6. author="yushunzhi"
  7. author_email="yushunzhi@sohu.com"
  8. author_location="Beijing, China">
  9.  
  10. <!-- Declare feature dependencies.
  11. The first one is not specific to Gmail contextual gadgets. -->
  12. <Requirefeature="dynamic-height"/>
  13.  
  14. <!-- The next feature, google.contentmatch, is required for all
  15. Gmail contextual gadgets.
  16. <Param>- specify one or more comma-separated extractor IDs in
  17. a param named "extractors". This line is overridden by the extractor ID
  18. in the manifest, but is still expected to be present. -->
  19. <Requirefeature="google.contentmatch">
  20. <Paramname="extractors">
  21. google.com:HttpLinkExtractor
  22. </Param>
  23. </Require>
  24. </ModulePrefs>
  25.  
  26. <!-- Define the content type and display location. The settings
  27. "html" and "card" are required for all Gmail contextual gadgets. -->
  28. <Contenttype="html"view="card">
  29. <![CDATA[
  30. <head>
  31. <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
  32. <style>
  33. html, body {
  34. color:#333333;
  35. font:12px Arial,Helvetica,sans-serif;
  36. margin:0;
  37. padding:0;
  38. </style>
  39. </head>
  40. <script src="http://www.tech126.com/gadgets/jquery-1.4.2.min.js" type="text/javascript"></script>
  41. <script type="text/javascript">
  42.  
  43. (function ()
  44. {
  45. var exp = /u.sohu.com/download/(d+)/(d+)/;
  46. var matches = google.contentmatch.getContentMatches();
  47. var numLoaded = 0;
  48. var exp_match = [];
  49. var url = '', bid = '', fileid = '';
  50. var img_postfix = ['jpg','jpeg','gif','png'];
  51. var matchList = document.createElement('ul');
  52. var listItem, childItem;
  53.  
  54. document.body.appendChild(matchList);
  55.  
  56. for(var i = 0 ; i < matches.length ; ++i)
  57. {
  58. url = matches.url;
  59. exp_match = url.match(exp);
  60. if (!exp_match)
  61. {
  62. continue;
  63. }
  64.  
  65. bid = exp_match[1];
  66. fileid = exp_match[2];
  67.  
  68. $.ajax(
  69. {
  70. url: "http://u.sohu.com/uFileInfo.action",
  71. dataType: 'jsonp',
  72. data: {'fileId':fileid},
  73. jsonp: 'callBack',
  74. success: function(json)
  75. {
  76. json = json || {};
  77. listItem = document.createElement('li');
  78. listItem.innerHTML = "File Url: " + "http://u.sohu.com/download/" + json.fileSe rver + "/" + json.fileId;
  79. childItem = document.createElement('div');
  80. childItem.innerHTML = "File Name: " + json.fileName;
  81. listItem.appendChild(childItem);
  82. childItem = document.createElement('div');
  83. childItem.innerHTML = "File Size: " + json.fileSize;
  84. listItem.appendChild(childItem);
  85. childItem = document.createElement('div');
  86. childItem.innerHTML = "File User: " + json.fileUser;
  87. listItem.appendChild(childItem);
  88. childItem = document.createElement('div');
  89. childItem.innerHTML = "File Type: " + json.fileType;
  90. listItem.appendChild(childItem);
  91. if (img_postfix.indexOf(json.fileType.toLowerCase()) >= 0)
  92. {
  93. childItem = document.createElement('img');
  94. childItem.src = "http://u.sohu.com/file/preview/image/" + json.fileServer + "/" + json.fileId;
  95. listItem.appendChild(childItem);
  96. }
  97. childItem = document.createElement('p');
  98. listItem.appendChild(childItem);
  99. matchList.appendChild(listItem);
  100. },
  101. timeout: 3000
  102. }
  103. );
  104. }
  105. gadgets.window.adjustHeight(200);
  106.  
  107. })();
  108.  
  109. </script>
  110. ]]><I></I>
  111. </Content>
  112. </Module>




这个Gadgets功能很简单,就是判断如果有Sohu U盘发送的文件链接,则后台使用Jsonp去获取该文件的一些信息


如果文件是图片,那么就生成一个缩略图展示出来


实现后,可以到Google marketplace上去创建一个List,最后不要submit激活,如果激活,Googel会收取$100的费用...


然后,添加到自己的Google Apps domain中去测试,在调试过程中,访问mail最好加上nogadgetcach=1的参数,不让其缓存,如:


https://mail.google.com/a/tech126.com/?nogadgetcache=1#


以下是运行这个Gadget后的截图:


当Https遇到了Iframe

最近,邮箱准备上全程的https服务


在把所有的页面引用的src全都改到https的路径后,通过https访问仍然会有浏览器的安全警告框


查了很久无果,后来在邱老大的提示下,才发现原来是Iframe导致的


Https中如果有Iframe,如果无src或者src中有document.wirte等,浏览器可能会认为是不安全的


以下是测试结果:



  1. 无src属性,IE6会有警告,IE8,Firefox均正常

  2. src="javascript:document.open();document.close();" ,IE下正常,Firfox下有警告

  3. src="javascript:void(0);",IE6有警告,IE8,Firefox均正常

  4. src="",IE6有警告,IE8,Firefox均正常


现在Mail前端的js中,有很多iframe的src不是指向到具体的页面,而是通过document.open(),document.write()来写入代码


当初,前端开发工程师可能是为了减少连接数,就这么实现的


在Https中这么做是不行的,只好src到一个空的blank.html页面,然后在js中再进行write


如果需要监听某个iframe的load完成事件,则上述办法也不行,只能实现一个真实的html了,里面加上对应的逻辑

解决不同浏览器上中文文件名的下载乱码问题

目前,我们的U盘和Mail中对含有中文文件名的下载处理都不是太好


在某些浏览器下,下载显示的文件名是乱码


我又顺便看了一下其他各邮箱和网盘的处理,只有QQ处理的比较好


现在时基本上每个浏览器都能正常显示中文的文件名


花了一些时间对IE,Firefox,Opera,Chrome,Safari这几个浏览器进行了测试


总结了一下,各浏览器能正确识别的编码格式,只要按照这样的编码来设置对应的Content-Disposition


那么应该就不会出现中文文件名的乱码问题了


 


首先,Content-Disposition值可以有以下几种编码格式


1. 直接urlencode:


    Content-Disposition: attachment; filename="struts2.0%E4%B8%AD%E6%96%87%E6%95%99%E7%A8%8B.chm"


2. Base64编码:


    Content-Disposition: attachment; filename="=?UTF8?B?c3RydXRzMi4w5Lit5paH5pWZ56iLLmNobQ==?="


3. RFC2231规定的标准:


    Content-Disposition: attachment; filename*=UTF-8''%E5%9B%9E%E6%89%A7.msg


4. 直接ISO编码的文件名:


    Content-Disposition: attachment;filename="测试.txt"


然后,各浏览器支持的对应编码格式为:


1.  IE浏览器,采用URLEncoder编码


2.  Opera浏览器,采用filename*方式


3.  Safari浏览器,采用ISO编码的中文输出


4.  Chrome浏览器,采用Base64编码或ISO编码的中文输出


5.  FireFox浏览器,采用Base64或filename*或ISO编码的中文输出


 


对应的Java代码如下:



折叠复制代码




  1. new_filename = URLEncoder.encode(filename, "UTF8");  

  2. // 如果没有UA,则默认使用IE的方式进行编码,因为毕竟IE还是占多数的  

  3. rtn = "filename="" + new_filename + """;  

  4. if (userAgent != null)  

  5. {  

  6.     userAgent = userAgent.toLowerCase();  

  7.     // IE浏览器,只能采用URLEncoder编码  

  8.     if (userAgent.indexOf("msie") != -1)  

  9.     {  

  10.         rtn = "filename="" + new_filename + """;  

  11.     }  

  12.     // Opera浏览器只能采用filename*  

  13.     else if (userAgent.indexOf("opera") != -1)  

  14.     {  

  15.         rtn = "filename*=UTF-8''" + new_filename;  

  16.     }  

  17.     // Safari浏览器,只能采用ISO编码的中文输出  

  18.     else if (userAgent.indexOf("safari") != -1 )  

  19.     {  

  20.         rtn = "filename="" + new String(filename.getBytes("UTF-8"),"ISO8859-1") + """;  

  21.     }  

  22.     // Chrome浏览器,只能采用MimeUtility编码或ISO编码的中文输出  

  23.     else if (userAgent.indexOf("applewebkit") != -1 )  

  24.     {  

  25.         new_filename = MimeUtility.encodeText(filename, "UTF8""B");  

  26.         rtn = "filename="" + new_filename + """;  

  27.     }  

  28.     // FireFox浏览器,可以使用MimeUtility或filename*或ISO编码的中文输出  

  29.     else if (u
    serAgent.indexOf(
    "mozilla") != -1)  

  30.     {  

  31.         rtn = "filename*=UTF-8''" + new_filename;  

  32.     }  

  33. }  






目前,我测试的情况,在几个浏览器上都能正常输入中文文件名


但,也许浏览器不同版本,可能还会有乱码的情况.....


 


 

使IE内核的浏览器web页面变灰

昨天是全国哀悼日,以纪念青海玉树地震遇难的同胞


网站的首页需要去除颜色,全部变灰


对于IE内核的浏览器,比较简单,加一个css样式即可:



折叠复制代码




  1. html  

  2. {    

  3.     filter:progid:DXImageTransform.Microsoft.BasicImage(grayscale=1);  

  4. }







对于非IE浏览器,则只能自己修改所有的CSS以及图片了(昨天请教了SAS的技术人员,没有别的捷径......)


今天,看到张宴的blog,也可以通过nginx的http_sub_module来实现


这个模块是用来对http的response进行查找替换的,在编译时,需要增加--with-http_sub_module选项



折叠复制代码




  1. location = /index.jsp


  2. {  

  3.   sub_filter  '</head>'  '<style type="text/css">html {filter:progid:DXImageTransform.Microsoft.BasicImage(grayscale=1);}</style></head>';

  4. }







具体我没有尝试,但我觉得这种方式,对于高并发的请求,效率可能会有问题

web页面中自动切换http/https

当我们的某个应用支持https后


就会有这样的需求:当用户使用https访问某个页面时,那么页面里多的所有元素也都应该是https的请求,反之亦然


通常会有以下2种办法:



  1. 在js中通过location.protocol来获取当前页面的Scheme,然后来生成对应的url

  2. 使用相对路径来实现:


  3. 折叠复制代码




    1. /js/pv_v204.js  

    2. ../images/pic.gif  

    3. css/style.css  

    4. //vip.sohu.com/pay/pay_auth.jsp  







             这几种相对路径都是合法的


             注意最后一种用法,对于需要的资源不在同一个域下时非常有用


             它省略了url中的Scheme部分,这样它就会根据当页面的Scheme来自动切换了

手机PushMail

用139邮箱的pushmail功能有一段时间了


总体感觉还是不错的,当有新邮件时,会自动连接GPRS,下载邮件


上网看了一些关于PushMail的基础知识,了解到了一些东西:



  1. 139的PushMail和Blackberry的Push原理类似,似乎都是采用短信触发客户端进行邮件收取动作。也即用户邮箱收到新邮件时,移动运营商会向手机发送一条短信,用户收到短信后,触发PushMail的客户端,连接gprs来下载邮件。我用的是WM系统,在注册表里可看到以下东西:
    [HKEY_LOCAL_MACHINESoftwareMicrosoftShellEventNetworkWDP16000PushSms]

    Command=WindowsPushSms.exe

    Class=PushSms

    WDP Port=1025
    看起来是使用了1025端口来接受那条短信的

  2. Ip PushMail:它的特点是手机会保持一个固定的IP地址,邮件服务器收到新邮件后会在第一时间根据IP地址将邮件推送到手机客户端上。好像尚邮采用的是IP push 的方式,支持目前市场上的全部主流手机平台,所有开通pop功能的邮箱,还可加密传送安全可靠,但是要达到实时Push效果的话,需要时刻在线,所以,这种方式比较耗电

  3. 很多“伪PushMail”:类似于手机上的pop客户端,定时不停的到服务器上去检测是否有新邮件到达,相当的耗电


相比而言,139邮箱的PushMail总体还算不错,不用时时在线,却能实时的收到邮件。

最新文章

最近回复

  • feifei435:这两个URI实际是不一样的
  • zsy: git push origin 分支 -f 给力!
  • 冼敏兵:简单易懂,good fit
  • Jack:无需改配置文件,看着累! # gluster volume se...
  • Mr.j:按照你的方法凑效了,折腾死了。。。。
  • zheyemaster:补充一句:我的网站路径:D:\wamp\www ~~菜鸟站长, ...
  • zheyemaster:wamp2.5(apache2.4.9)下局域网访问403错误的...
  • Git中pull对比fetch和merge | 炼似春秋:[…] 首先,我搜索了git pull和git fe...
  • higkoo:总结一下吧, 性能调优示例: gluster volume s...
  • knowaeap:请问一下博主,你维护的openyoudao支持opensuse吗

分类

归档

其它