-
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();
%>