该实例原型来源于网上,不过所有功能都是我自己敲键盘实现的,其中还使用了点AJAX框架的东东。
该实例完全实现了网盘的功能,也可以做邮件管理,思路是一样的。
其中的主要功能有六项,在此我将一一分析。
一是点击目录或文件的时候,如是目录,则将目录下的文件和文件夹显示出来:
若是文件,则下载该文件。
还有,如再点击展开的目录,则需将其缩回。
在此我是依靠JavaScript与webservice实现的,前台的js代码用来控制网页,webservice提供前台与服务器交互的接口。
而所有的文件信息,都呈现在一个DIV之中:
Code
<td bgcolor="#ccccff">
<div id="fileDiv"></div>
</td>
初始化时,JavaScript通过webservice获得根目录下的所有文件,通过改变DIV的innerHTML属性呈现到页面上:
Code
//------------------------------初始化操作-------------------------------------------
var id;
function init() { AjaxFileManage.FileInfoService.getFilesAndDirs(".",Begin); }
function Begin(fds)
{
var div = document.getElementById("fileDiv");
var arr = [];
for (var i=0; i<fds.length; i++)
{
arr.push(String.format("<span id='{3}' open='false' isRender='false' belong=''><input type='checkbox' name='checks' /><a href='javascript:click(\"{3}\")'>{0}</a> {1} {2}<br /></span>",
fds[i].Name,fds[i].FileSize,fds[i].CreateTime,fds[i].FileName));
}
div.innerHTML = arr.join("");
}
AjaxFileManage.FileInfoService.getFilesAndDirs是名字空间AjaxFileManage下的webservice,FileInfoService下的webmethod,getFilesAndDirs。
Begin则是回调函数。
应为据说IE下的字符串+操作要比FF慢一千倍,所以我这里采用了数组对象push和join方法,其实由于循环大不到那里去,用+操作也没事。
可以看到,我在span标签中加了几个自定义元素open、isRender、belong,open用来标识该目录是否是展开状态,isRender标识该目录下的所有文件信息是否已从后台拿到了,如果是的话下次点击就不需要在叨扰服务器了,否则需要与服务区交互。belong这个属性我本来是想用来划分严格的阶级体系,以方便管理,结果后来发现没必要。所以这个属性就不必管它了。
当点击一个目录的时候,首先判断目录下的文件信息是否已经得到,这里可利用如上的isRender属性来判断。如果已经得到的话就无需再与服务器交互获取信息,否则反之。然后在观察open属性,如果已是打开状态的话就关闭,关闭就打开。
Code
//-----------------------------单击打开关闭文件夹操作-------------------------------
function openClick(fds) {
Render(id,fds);
openOrclose(id);
}
function click(_id)
{
id = _id;
AjaxFileManage.FileInfoService.getFilesAndDirs(_id,openClick);
}
function openOrclose(id) {
var display;
if($(id).getAttribute("open") == "true")
{
display = "none";
$(id).setAttribute("open","false");
}
else
{
display = "";
$(id).setAttribute("open","true");
}
$(id).nextSibling.style.display = display;
}
//将文件和文件夹在页面上呈现出来
function Render(id,fds) {
if ($(id).getAttribute("isRender") == "true")
return;
var span = document.createElement("span");
var arr = [];
for (var i=0; i<fds.length; i++)
{
var spaces = GetSpace(id);
if (fds[i].IsDir == true)
arr.push( String.format("<span id='{3}' open='false' isRender='false' belong='{4}'>{5}<input type='checkbox' name='checks' /><a href='javascript:click(\"{3}\")'>{0}</a> {1} {2}<br /></span>",
fds[i].Name,fds[i].FileSize,fds[i].CreateTime,fds[i].FileName,id,spaces));
else
arr.push( String.format("<span id='{3}' belong='{4}'>{5}<input type='checkbox' name='checks' /><a href='javascript:download(\"{3}\")'>{0}</a> {1} {2}<br /></span>",
fds[i].Name,fds[i].FileSize,fds[i].CreateTime,fds[i].FileName,id,spaces));
}
span.innerHTML = arr.join("");
insertAfter(span,$(id));
$(id).setAttribute("isRender","true");
}
//得到当前文件应当缩进的空格
function GetSpace(path) {
var spaces = " ";
for (var i=0; i<path.length; i++)
{
if (path.charAt(i) == ',')
spaces += " ";
}
return spaces;
}
//在源节点后插入新节点
function insertAfter(newNode, refNode) {
if (refNode.nextSibling) {
refNode.parentNode.insertBefore(newNode,refNode.nextSibling);
} else {
refNode.parentNode.appendChild(newNode);
}
}
接下来是对文件的单击操作,当单击一个文件时,便下载该文件。我采用的是隐藏框架以及HTTPHandle实现的。
Code
<form id="downloadForm" action="DownLoadHandler.ashx" method="post" target="iframe" >
<input type="hidden" id="specialName" name="specialName" />
</form>
<iframe id="iframe" style="display:none;"></iframe>
JS:
Code
//------------------------------下载操作-------------------
function download(_id)
{
$("specialName").value = escape(_id);
$("downloadForm").submit();
}
httpHandle:
Code
public void ProcessRequest (HttpContext context) {
string specialName = context.Server.UrlDecode(context.Request.Form["specialName"]);
if (specialName == null)
{
return;
}
string path = context.Server.MapPath("client");
string[] es = specialName.Split(new char[] { ',' });
foreach (string str in es)
{
path += "\\" + str;
}
FileInfo file = new FileInfo(path);
context.Response.ContentEncoding = System.Text.Encoding.GetEncoding("UTF-8");
context.Response.AddHeader("Content-Disposition", "attachment; filename=" + context.Server.UrlEncode(file.Name));
context.Response.AddHeader("Content-length",file.Length.ToString());
context.Response.ContentType = "appliction/octet-stream";
context.Response.WriteFile(file.FullName);
return;
}
忘了说,在页面上包含每一个文件及文件夹的span标签都有一个特殊的id,这个id指示了该文件或文件夹的路径,比如回收箱下的123.jpg这个文件,它的id就是"回收箱,123.jpg",这个id是一个特殊名字,specialName。服务器获取这个特殊名字,便可将它解析成绝对路径,以便正确访问文件。
好了,点击的功能就说到这。
第二个实现是文件夹的创建,相对来说,下面就比较简单了。
当选择一个目录后,便在选择的目录下创建相应文件夹,如果未选择,则在主目录下创建文件夹。当然,创建文件夹的工作由服务器完成,而一些所需的信息(路径、文件夹名)则由JavaScript通过webservice传递给服务器。
Code
//------------------------------文件夹创建操作------------------------------
function createResult(msg) {
alert(msg);
init();
}
function createOp() {
var ids = select();
var path;
if (ids.length > 1) {
alert("一次只能在一个目录下创建文件夹!");
return;
}
else if (ids.length == 0) {
alert("将在主目录下创建文件夹!");
path = ".";
}
else if ($(ids[0]).getAttribute("open") == null) {
alert("请在目录下创建文件夹!");
return;
}
else {
alert("将在 " + ids[0].replace(",","\\") + " 下创建文件夹!");
path = ids[0];
}
var name = prompt("您要创建的目录名称:","");
if (name == null)
return;
else if (!name.match(/\w{1,20}/)) {
alert("目录名称不规范!");
return;
}
else {
AjaxFileManage.FileInfoService.createDir(path,name,createResult);
}
}
下面是删除操作、剪切粘贴操作、重命名操作以及文件的上传操作,这些都是非常简单的,我也就不废话了。
最后还有一点要注意的是,由于是BS程序,可能会出现客户端没权限访问相应路径的问题,据我所知有两种解决方法,一种是单击相应目录的属性,在安全选项中添加ASPNET用户,并给予相应权限(需注意XP下安全选项默认情况是隐藏的,需在文件夹选项中打开它),还有一种是采用ASP.NET的身份模拟。至于如何使用的详细问题,百度一下就OK了。
代码下载