28、使用cookie、iframe进行客户端与服务器端的通信

  • cookie

cookie是第一个JavaScript可以利用客户端——服务器端之间的交互手段。浏览器向服务器发送请求时,为这个服务器存储的cookie会与其他信息一起发送到服务器。这使得JavaScript可以在客户端设置一个cookie,之后服务器端就能够读取它了。

cookie的组成

  • 名称——每个cookie由一个唯一的名称表示。名称不区分大小写,但最好是区分,因为有些服务器端软件是这样的。
  • 值——保存在cookie中的字符串值。这个值在存储之前必须用encodeURIComponent()对其进行编码,以免丢失数据或占用了cookie。注:名称和值一起的字节数不能超4KB。
  • 域——出于安全考虑,网站不能访问由其他域创建的cookie。创建cookie后,域的信息会作为cookie的一部分存储起来。不过,虽然这不常见,还是可以覆盖这个设置以允许另一个网站访问这个cookie的。
  • 路径——另一个cookie的安全特征,路径限制了对WEB服务器上的特定目录的访问。例如:可指定cookie只能从http://www.wrox.com/books中访问,这样就不能访问http://www.wrox.com/上的网页了,尽管都在同一个域中。
  • 失效日期——cookie何时应该被删除。默认情况下,关闭浏览器时,即将cookie删除;不过,也可以自己设置删除时间。这个值是个GMT格式的日期(可以使用Date对象的toGMTString()方法),用于指定应该删除cookie的准确时间。因此,cookie可在浏览器关闭后依然保存在用户的机上。如果你设置的失效日期是以前时间,则cookie被立即删除。
  • 安全标志——一个true/false值,用于表示cookie是否只能从安全网站(使用SSL和https协议的网站)中访问。可以将这个值设置为true以提供加强的保护,进而确保cookie不被其他网站访问。

其他安全限制

为确保cookie不能恶意使用,浏览器还对cookie的使用进行了一些限制:

  • 每个域最多只能在一台用户的机器上存储20个cookie。
  • 每个cookie的总大小不能超过4096字节。
  • 一台用户的机器上的cookie的总数不能超过300个。

另外,一些新的浏览器还对cookie进行了严格控制,可以让用户阻止所有的cookie,阻止某些未知网站的cookie或者在创建cookie时进行提示。

JavaScript中的cookie

document对象有个cookie属性,是包含所有给定页面可访问的cookie的字符串。cookie属性很特别,因为将这个cookie属性设置为新值只会改变对页面可访问的cookie,并不会真正改变cookie(属性)本身。

要创建一个cookie,必须按照下面的格式创建字符串:

cookie_name=cookie_value; expires=expiration_time; path=domain_path; domain=domain_name;secure

只有第一部分对设置cookie是必需的,其他部分都可以省。然后将这个字符串复制给document.cookie属性,即可创建cookie。如:

document.cookie='name=Nicholas';

document.cookie='book='  +  encodeURIComponent('Professional JavaScript');

读取document.cookie的值即可以访问这些cookie,以及所有其他可以从给定页面访问的cookie。如果在运行上面两行代码后显示 document.cookie 的值,则出现'name=Nicholas;book=Professional%20JavaScript'。注,即使创建了其他的cookie属性,如失效时间,document.cookie也只返回每个cookie的名称和值,并用分号来分隔这此cookie。

因为创建和读取cookie均需记住它的格式,大部分开发人员用函数来处理这些细节。cookie操作函数:

//创建cookie
function setCookie(sName, sValue, oExpires, sPath, sDomain, bSecure) {
	var sCookie = sName + "=" + encodeURIComponent(sValue);
	//除sName, sValue外,其他参考可选,所以使用前要判断是否传入
	if (oExpires) {
		//时间要是GMT格式
		sCookie += "; expires=" + oExpires.toGMTString();
	}
	if (sPath) {
		sCookie += "; path=" + sPath;
	}
	if (sDomain) {
		sCookie += "; domain=" + sDomain;
	}
	if (bSecure) {
		sCookie += "; secure";
	}
	document.cookie = sCookie;
}
//通过传入的名字获取cookie的值
function getCookie(sName) {
	var sRE = "(?:; )?" + sName + "=([^;]*);?";
	var oRE = new RegExp(sRE);
	if (oRE.test(document.cookie)) {
		return decodeURIComponent(RegExp["$1"]);
	} else {
		return null;
	}
}
//删除cookie
function deleteCookie(sName, sPath, sDomain) {
	//删除cookie必须给出与创建它时一样的路径和域信息。
	var sCookie = sName + "=; expires=" + (new Date(0)).toGMTString();
	if (sPath) {
		sCookie += "; path=" + sPath;
	}
	if (sDomain) {
		sCookie += "; domain=" + sDomain;
	}
	document.cookie = sCookie;
}
 
<html>
    <head>
        <title>Cookies Example</title>   
        <script type="text/javascript">
   					//引用上面脚本...                        
        </script>           
    </head>
    <body>
        <script type="text/javascript">
            alert("Setting cookies...");
            setCookie("name", "Nicholas");
            setCookie("book", "Professional JavaScript");
            
            
            alert("The value of cookie 'name' is " + getCookie("name"));
            alert("The value of cookie 'book' is " + getCookie("book"));
        
            alert("Deleting cookies...");
            deleteCookie("name");
            deleteCookie("book");
            
            alert("The value of cookie 'name' is " + getCookie("name"));
            alert("The value of cookie 'book' is " + getCookie("book"));
            
        </script>
 
    </body>
</html>

 jsp服务器端的cookie

先可以通过request对象的getCookies()方法,返回一组Cookies对象,每个对象有以下方法:

  • getComment()——返回描述cookie目的的注释,如果cookie没有注释则为null
  • getDomain()——返回cookie设置的域名称
  • getMaxAge()——返回cookie的最大寿命,单位为称;默认情况下为-1,表示cookie会持续到浏览器关闭
  • getName()——返回cookie的名称
  • getPath()——返回服务器为浏览器提供的返回cookie的路径
  • getSecure()——如果浏览器只通过安全协议发送cookie则为true,否则为false
  • getValue()——返回cookie的值
  • getVersion()——返回与cookie相关的协议的版本
  • setComment(String perpose)——指定描述cookie目的的注释
  • setDomain(String pattern)——指定给出cookie的域
  • setMaxAge(int expiry)——指定cookie的最大寿命,单位为秒
  • setPath(String uri)——指定浏览器返回cookie的路径
  • setSecure(boolean flag)——指示浏览器cookie是否只能通过安全协议,如HTTPS或者SSL来传送
  • setValue(String newValue)——创建cookie后,为cookie指定一个值
  • setVersion(int v)——指定与cookie相关的协议的版本
<%!//读取cookie
	public static Cookie getCookie(HttpServletRequest request, String name) {
		Cookie[] cookies = request.getCookies();
		if (cookies != null) {
			for (int i = 0; i < cookies.length; i++) {
				if (cookies[i].getName().equals(name)) {
					return cookies[i];
				}
			}
		}
		return null;
	}%>

<%
	//创建cookie
	Cookie nameCookie = new Cookie("name", "Nicholas");
	nameCookie.setDomain("http://www.wrox.com");
	nameCookie.setPath("/books");
	response.addCookie(nameCookie);
%>

<%
	//删除cookie
	Cookie cookieToDel = getCookie(request, "name");
	cookieToDel.setMaxAge(0);
	response.addCookie(cookieToDel);
%>

在客户端与服务器端之间传递cookie

与Javascript的交互,常常是服务器在发送响应前创建一个cookie(也许在servlet或者其他运行在服务器上的应用中)。然后带有胜于获取cookie值的Javascript的页面就会载入。

例如,假设你在网站上创建一个反馈表单,上面要求用户输入名字、电子邮件地址及反馈消息。你可以让用户将他们的名字与电子邮件地址保存下来,以便他们下次访问并要留下反馈时,可以无需再输入这两个字段。思路如下:

首先通过在服务器端创建相应的Cookie,并通过response回送给客户端保存下来(如果浏览器支持Cookie会自动保存),然后,将来某天用户进入上面那个面页时,通过JavaScript调用Cookie读取相应的值。

其实创建与读取Cookie过程完全可以在服务上全部实现,不需要由客户端读取。

  • iframe

可以通过iframe来模拟ajax的后台请求,即在不刷新面页的情况下能与服务器进行通信。

主页面main.htm:

<html> 
    <head> 
        <title>iframe 隐藏框架实例 (主页面) </title> 
        <script type="text/javascript"> 
        
		//全局变量,在不刷新情况下可以重复请求而不用多次创建 
		var oHiddenFrame = null;
		function getServerInfo() { 
			//如果还没有创建过,则创建 
			if (oHiddenFrame == null) { 
				//使用DOM的createElement创建框架对象 
				oHiddenFrame = document.createElement("iframe");
				/*必须同时将name与id设置为hiddenFrame,以保证在大部分浏览 
				 中都能正常工作(有些使用name,有些使用id)*/
				oHiddenFrame.name = "hiddenFrame";
				oHiddenFrame.id = "hiddenFrame"; 
				//高度与宽度都必须为0 
				oHiddenFrame.style.height = "0px";
				oHiddenFrame.style.width = "0px"; 
				//位置设置为绝对 
				oHiddenFrame.style.position = "absolute"; 
				//设置为不可见 
				oHiddenFrame.style.visibility = "hidden"; 
				//最后将创建的框架添加到body对象中去 
				document.body.appendChild(oHiddenFrame);
			}
			/*iframe创建好并添加后,大部分浏览器(尤其是Mozilla与Opera)会需要一小段时间(毫秒级) 
			   来认出新的框架并将其添加到帧集合中。考虑此问题,应该用setTimeout()函数使发送请求的 
			   操作等待10毫秒。*/
			setTimeout(function () { 
				//为document中的hiddenFrame框架设置要请求的URL 
				frames["hiddenFrame"].location.href = "iframeResponse.jsp";
			}, 10);
		} 
		//处理服务器响应消息,供响应页面HiddenFrameExampleCom2.htm中脚本回调 
		function handleResponse(sResponseText) {
			alert("服务器回应的响应信息: " + sResponseText);
		}


        </script> 
    </head> 
    <body> 
        <p>点击按键通过iframe隐藏框架向服务器发送请求. </p> 
        <input type="button" οnclick="getServerInfo()" value="Get Server info" /> 
    </body> 
</html> 

响应页面iframeResponse.jsp实现:

<html> 
    <head> 
        <title>iframe 隐藏框架实例 (响应页面) </title> 
        <script type="text/javascript"> 
        /*在服务器处理完后,将处理的数据送到此页面中,再由此页面将数据 
        进一步的传送给主页面创建iframe框架的页面),这一过程通过触发window的onload事件调用主页面的handleResponse函数来完成*/ 
            window.onload = function () { 
                parent.handleResponse(' <%=request.getAttribute("responseData")%>'); 
            }; 
        </script> 
    </head> 
    <body>      
    </body> 
</html> 

上传文件进度条实现

上传文件时如果要实现真实的进度条,则要借助于iframe框架。因为普通的文件上传方式会在提交后,页面会变白且处于等待服务器相应,所以上传时不能采用普通方式。可以使用iframe在上传时不出现白页面,且可以在上传文件的当前页面实现进度条。

上传页面代码大体如下:

...
<iframe name="upload_file" id="upload_file" style="display: none;"></iframe>

<div id="add_form">
	<form id="addForm" method="post" target="upload_file"
		enctype="multipart/form-data" action='...'>
		<input type="file" style="width: 210;" id="MsisdnFile"
			name="MsisdnFile">
		...
	</form>
</div>
...

<table width="100%" border="0" cellspacing="0" cellpadding="
	hight="100%">
	<tr>
		<td>
			<table width="100%" cellapdding="0" cellspacing="0" border="0"
				id="percnet_tb" style="display: inline;">
				<tr height="20">
					<td></td>
				</tr>

				<tr align="center">
					<!--处理中,请稍后-->
					<td>
						<div id="wait">
							处理中,请稍后...
						</div>
					</td>
				</tr>

				<tr>
					<td align="center">
						<!--进度条-->
						<div align="left" class='prog-border'>
							<div id="percent_div"></div>
						</div>
					</td>
				</tr>

				<tr align="center">
					<!--进度值-->
					<td>
						<div id="percent">
							0%
						</div>
					</td>
				</tr>

			</table>
		</td>
	</tr>
</table>
...

 

设置进度条样式相关js:

//...
//设置进度条宽度
$("percent_div").style.width = percent + "%";
//设置进度条值
$("percent").innerText = percent + "%";

//进度条样式设置
if (percent != "0") {
	setBarStyle();
} else {
	intialBarStyle();
}
//...
/**
* method:初始化进度条样式
*/
function intialBarStyle() {
	var percent_div = $("percent_div");
	percent_div.style.border = "0px solid #000";
	percent_div.style.margin = "2px";
	percent_div.style.fontSize = "11pt";
	percent_div.style.width = "0%";
}
/**
* method:进度非零时进度条样式
*/
function setBarStyle() {
	var percent_div = $("percent_div");
	percent_div.style.heigth = "11px";
	percent_div.style.background = "#178399";
	percent_div.style.border = "1px solid #000";
	percent_div.style.margin = "2px";
	percent_div.style.padding = "0";
	percent_div.style.fontSize = "10pt";
}

 

其他的工作是就是用ajax与服务器进行异步通信,获取进度值而已。

 

 

既然这里说到了上传,下面随便贴一下下载的方面要注意的:

<%
	response.setContentType("application/octet-stream;charset=UTF-8");

	String logType = request.getParameter(Const.PARA_LOGTYPE);

	String currDateStr = Util.getDateTimeStr(Util.getCurrDate(), Const.YYYYMMDDHHMMSS);
	String filePrefix = null;
	if (Const.SUCC_LOG_DETAIL.equals(logType)) {
		filePrefix = "SUCC_LOG_";
	} else if (Const.UNSUCC_LOG_DETAIL.equals(logType)) {
		filePrefix = "FAIL_LOG_";
	} else if (Const.UNDONE_LOG_DETAIL.equals(logType)) {
		filePrefix = "UNDONE_LOG_";
	}

	String paramLook = request.getParameter("look");
	String paramSave = request.getParameter("save");

	String method = null;
	if (paramLook != null) {
		method = "inline";
	} else {
		method = "attachment";
	}
	response.setHeader("Content-Disposition", method + ";filename=" + filePrefix + currDateStr + ".txt");
	String logStr = (String) request.getAttribute(Const.KEY_OPRNFOSTR);
	response.setHeader("Accept-Ranges", "bytes");
	response.setHeader("Accept-Length", (new Integer(logStr.getBytes().length)).toString());
	System.out.println(logStr);
	PrintWriter os = response.getWriter();
	os.print(logStr);
	os.flush();
	os.close();
%>
 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值