动易swCMS6.5网站的上传文件管理器及判断文件是否失效的功能模块分析
动易cms6.5网站后台的上传文件管理模块由6个页面组成,现分别简介如下:
1)Admin_UploadFile.asp
频道上传文件后台管理页的框架页
上框架为Admin_UploadFile_Top.asp
下框架分左和右
左为Admin_UploadFile_Left.asp
右为Admin_UploadFile_Main.asp
2)Admin_UploadFile_Top.asp
框架页的头部
用于获取框架页传递的参数UploadDir,即该频道上传文件的目录名
3)Admin_UploadFile_Left.asp
上传文件的树形目录结构,设计成资源管理器的风格
通过FSO 的Folder对象来获取上传目录的子目录集合,代码如下:
Set FolderObj = fso.GetFolder(Server.MapPath(UpFilesPath)) '获取上传根目录的绝对路径
Set SubFolderObj = FolderObj.SubFolders '上传根目录的子文件夹集合
以下是我测试时使用的注释代码:(因为我对FSO的Folder对象印象不深)
'response.Write(FolderObj) '输出上传根目录的绝对路径
'例如: G:/动易SiteWeaver6.5版/swcms/jiaoxuekeyan/UploadFiles_3443
'response.Write(TypeName(SubFolderObj)) '输出的值为Folders
'备注: SubFolderObj不是数组类型的值,而是Folder对象的集合Folders
'response.Write(SubFolderObj.Count) '子文件夹的个数
获取得到的子文件夹集合后,执行一个循环
For Each FolderItem In SubFolderObj
‘完成此目录下子文件夹的输出显示
……
If UpLoadNumber = SubFolderObj.Count Then '若为true,则所有的子文件夹显示完毕
Response.Write (GetChildFolderList(UpFilesPath & FolderItem.name, "", True, ""))
Else '否则继续输出子文件夹
Response.Write (GetChildFolderList(UpFilesPath & FolderItem.name, "", False, ""))
End If
UpLoadNumber = UpLoadNumber + 1 '累积已显示的子文件夹个数
Next
因为要逐级地输出所有目录的子目录以构成目录树的形式,
所以这里编写了一个“递归函数”来实现逐级获取子目录并显示
Function GetChildFolderList(FolderID, Str, EndNodeTF, TempAllParentID)
…………
Set FolderObj = fso.GetFolder(Server.MapPath(FolderID))
Set SubFolderObj = FolderObj.SubFolders
For Each FolderItem In SubFolderObj
…………
GetChildFolderList = GetChildFolderList & GetChildFolderList(FolderID & "/" & FolderItem.name, ImageStr, TempEndNodeTF, AllParentID)
‘执行递归函数实现逐级显示子目录
ChildFolderNumber = ChildFolderNumber + 1
‘累积已显示的子文件夹的个数
Next
Set FolderObj = Nothing
Set SubFolderObj = Nothing
End Function
该递归函数的完整代码可查看文件Admin_UploadFile_Left.asp
主要由4个JS函数完成该目录树的前台功能
ClickClassImg(ClickObj,ClassID) //展开和折叠目录
ShowChildClass(ID) //显示目录所包含的子目录列表
ChangeImg(Obj,OpenTF) //更换目录的状态图片
HideChildClass(ID) //隐藏目录所包含的子目录列表
另外,整个目录树的表格<table>中增加了一个自定义属性RootDir
例如:<table id='RootDir' RootDir='/jiaoxuekeyan/UploadFiles_3443/' …… >
RootDir为自定义属性,表示频道上传文件的根目录
每个上传目录所在的表格的行<tr>中增加了三个自定义属性AllParentID,ParentID,ClassID
例如:<tr AllParentID=”/jiaoxuekeyan/UploadFiles_3443/ “
ParentID=”/jiaoxuekeyan/UploadFiles_3443/ “
ClassID=”/jiaoxuekeyan/UploadFiles_3443/ 200802” …… >
AllParentID表示该目录的所有上级目录(若存在多个则用“,”分隔)
ParentID表示父目录
ClassID表示当前目录
这些JS函数通过DOM对象获取相关的属性值后执行实现上传文件“目录树”的前台功能。
点击目录树中的目录名后将链接到Admin_UploadFile_Main.asp文件中
同时将ChannelID,UploadDir,CurrentDir参数传递
若不为上传目录下的文件夹,还要传递ParentDir参数
4)Admin_UploadFile_Main.asp
上传文件管理模块的核心文件,则文件管理器的功能有:
<1>以详细信息方式 或 以缩略图方式 显示上传文件列表及子目录列表
相关的过程是:
GetUploadFileStyle() ‘获取cookie中保存的ShowFileStyle参数值.
接着执行注释中的操作:
Select Case ModuleType '根据频道模块类型获取该频道的所有图片,用字符"|"来分隔
strFiles = LCase(strFiles) '获取该频道的所有上传文件
<2>全选/取消全选上传的文件 / 预览缩略图 / 左栏树形目录的开关 / 排序
相关的JS函数为:
function CheckAll(form)
function unselectall()
function preloadImg(src)
function switchBar(obj)
function reSort(which) ‘传递用于排序的文件属性,可为:文件名/大小/类型/修改时间
<3> 通过传递的参数值调用相应的过程来实现文件管理器的如下功能(即:注释的文本),
以下所有的过程都定义在本文件中
Select Case Action '根据传递的参数执行相应操作
Case " Del "
Call DelFiles '删除文件
Case "DelThisFolder"
Call DelThisFolder '删除目录
Case "DelCurrentDir"
Call DelCurrentDir '删除当前目录
Case "DelAll"
Call DelAll '删除全部
Case "DoAddWatermark" ‘以下两个过程的执行需要安装Jpeg图象处理组件
Call DoAddWatermark '给图片增加水印
Case "DoAddWatermark_CurrentDir"
Call DoAddWatermark_CurrentDir '给当前目录下的图片增加水印
Case Else
Call main
‘过程main()初始化本页内容的显示
End Select
过程Main()的代码主要就是实现文件的排序功能 以及 选择上传文件的浏览方式
所用到的知识点包括:
FSO的File对象的属性
动态数组的运用
根据排序字段值的类型选择合适的方法进行排序,
例如:对字符串值的大小比较用StrComp()函数
对上传文件的数组完成要求的排序,通过执行一个二层循环来完成排序,省略的代码如下:
'=======排序开始=======
For i = FileCount To 0 Step -1
minmax = theFiles(0)(sortBy)
minmaxSlot = 0
For j = 1 To i
………………
Next
If minmaxSlot <> i Then
temp = theFiles(minmaxSlot)
theFiles(minmaxSlot) = theFiles(i)
theFiles(i) = temp
'排序完成后将序号作为元素的序号
End If
Next
'=======排序结束=======
有兴趣的朋友可以找到完整的代码来阅读。
<4>最后根据cookie中保存的ShowFileStyle参数值来选择上传文件的显示方式:
If ShowFileStyle = 1 Then
Call ShowFileDetail '以缩略图方式显示文件的过程
Else
Call ShowFileThumb '以详细信息方式显示文件的过程
End If
下面将对以上提到的两过程ShowFileDetail() 和 ShowFileThumb()的部分代码进行分析:
过程一:ShowFileDetail()以详细信息方式显示,
其包含两个过程分别用于文件夹列表的显示和文件列表的显示::
Call ShowFileDetail_fol '输出当前目录下的文件夹列表
Call ShowFileDetail_Fil '输出当前目录下的文件列表
该过程还调用预览图片缩略图时显示提示信息的函数:
Function GetFileContent(ByVal sPath, sType)
缩略图的显示则由JS函数function ShowADPreview(ADContent)来实现
显示缩略图的浮动的<div>标签的显示和定位由ShowJS_Tooltip过程中的js代码来实现
若服务器安装了Jpeg图片处理组件,则输出如下内容;若未安装,则不显示以下内容
If IsObjInstalled("Persits.Jpeg") = True Then
Response.Write " <br><input type='submit' name='Submit3' onClick=""document.myform.Action.value='DoAddWatermark'"" value='给选中的图片添加水印' > <input type='submit' name='Submit4' onClick=""document.myform.Action.value='DoAddWatermark_CurrentDir'"" value='给当前目录添加图片水印' >"
End If
过程二:ShowFileThumb()以缩略图方式显示
该过程仅调用了本页中定义的分页函数showpage2(strFileName, totalPut, MaxPerPage)
其代码按执行的顺序编写,条理清晰,顺着代码阅读即可。
重点提一下这句实现缩略图换行的代码。这里是4个/行
If FileNum Mod 4 = 0 Then Response.Write "</td><tr class='tdbg'>"
'=========每行显示4个图片文件,满4个则换行==========
两过程删除文件夹及文件,全选和取消全选等操作所调用的过程和函数都是相同的。
这些过程和函数也都定义在本文件Admin_UploadFile_Main.asp中,
想具体了解的朋友可找来阅读。
5)Admin_UploadFile_Clear.asp
该文件的作用就是清理该频道无用的上传文件,
“判断文件是否失效”的核心代码就包含在该文件中。
该核心代码设计思路分析如下:
首先获取该频道的所有上传文件以及文章内容中所包含的所有<img>图片标签,
以文章频道来举例:
sql = "select UploadFiles,Intro from PE_Article where ChannelID=" & ChannelID
strFiles = strFiles & "|" & rs(0) '获取所有文章的上传文件,用"|"分隔
ItemIntro = ItemIntro & "|" & rs(1) '获取所有文章的内容,用"|"分隔
使用正则表达式选择出文章内容中所有的<img>标签
regEx.Pattern = "<img.+?[^/>]>" '查询内容中所有 <img..>
Set Matches = regEx.Execute(ItemIntro)
将内容中所有的<img>标签累计起来:
tempStr = tempStr & "|" & Match.value '累计数组
再次通过正则表达式获取src=图片的链接
regEx.Pattern = "src/s*=/s*.+?/.(" & UpFileType & ")" '查询src =内的链接
再次通过正则表达式替换”src=”字符
regEx.Pattern = "src/s*=/s*" '过滤 src =
tempStr = regEx.Replace(tempStr, "")
最后得到所有的上传文件和文件内容中的所有使用的图片文件名
strFiles = strFiles & tempStr
得到所有使用的图片文件名后,接下来就通过执行两个循环来判断上传目录
和上传目录下的子目录中的文件是否包含在数据库存储的上传文件名中,
即是否包含在变量strFiles的值中。
若在,则该文件有效;若不在则该文件无效,则被删除。
循环一:
For Each theFile In theFolder.Files ‘循环判断上传根目录下的所有文件
If InStr(strFiles, LCase(theFile.name)) <= 0 Then
theFile.Delete True
'若该上传目录下的文件不包含在数据库存储的上传文件名中,则被删除
i = i + 1 '累计被删除的文件个数
End If
Next
循环二:
For Each theSubFolder In theFolder.SubFolders ‘上传根目录下的所有子文件夹
For Each theFile In theSubFolder.Files ‘循环判断子文件夹下的所有文件
If InStr(strFiles, LCase(theSubFolder.name & "/" & theFile.name)) <= 0 Then
theFile.Delete True
'若该上传目录下的子文件夹中的文件不包含在数据库存储的上传文件名中,则被删除
i = i + 1 '接着“循环一”继续累计被删除的文件个数
End If
Next
Next
经过实验发现,
确实只能删除上传根目录下的无效文件和上传目录根目录下的子文件夹中的无效文件。
再深层次的目录则无法判断。
其实这也足够了,比如我在测试时
频道“科研天地”的上传根目录为UploadFiles_3443
这是网站给我的自定义频道“科研天地”建立的上传文件根目录
当有文件上传时,会在UploadFiles_3443下再建立子文件夹200802
子文件夹之所以取名为200802是因为存放的是2008年2月上传的图片文件
6)Admin_UploadFile_Style.asp
由于本文件的唯一作用就是通过回传上传文件显示方式的参数,
实现Admin_UploadFile_Main.asp中的上传文件
是以“详细信息方式”还是以“缩略图方式”来显示
将http:/Admin_UploadFile_Style.asp?ShowFileStyle=1
传递的ShowFileStyle参数的值1保存到cookies中,代码为:
Response.cookies("ShowFileStyle") = ShowFileStyle '将上传文件的显示样式保存到cookies中
然后返回到刚才跳转到本页的源地址去,代码为:
Response.Redirect request.servervariables("http_referer") '从哪里链接到该文件的就回哪里去
即本文件起到一个“中转站”的作用。
其核心知识点就是request.servervariables("HTTP_REFERER")的应用
下面是我转的关于request.servervariables("HTTP_REFERER")的一帖子
以此来补充介绍一下request.servervariables("HTTP_REFERER")的用途:
其返回的是调用这个asp页面的是那个页面,
即看这个页面是被哪个页面所调用的,
这么跟你说吧:
有a.asp和b.asp两个页面,
在a.asp中点击链接到b.asp,
或是a.asp中用表单提交数据到b.asp,
或是用脚本跳转到b.asp,
那么在b.asp中用request.servervariables("HTTP_REFERER")方法
取得的字符串就是a.asp的URL路径。
注意:该URL路径包括a.asp后传递的参数
若是由a.asp?action=add链接到b.asp
则b.asp中调用request.servervariables("HTTP_REFERER")
取得的字符串就是a.asp?action=add
总结:
“上传文件管理器”的核心知识点其实也就是FSO的应用
我转贴的一篇关于FSO的文章《ASP中FSO功能详细介绍》
即可以作为学习也可以作为复习来阅读,
文章中包含的FSO的几个常用实例建议初次学习的朋友们实际操练以下其代码,
对理解和增加印象会很有帮助:
文章《ASP中FSO功能详细介绍》的链接:http://blog.youkuaiyun.com/kof98cs/archive/2008/03/09/2159320.aspx
“判断文件是否失效”
核心代码都包含在Admin_UploadFile_Clear.asp中,
通过阅读我们发现从数据库获取所有使用的上传文件信息后,
就是通过一系列的正则表达式对上面获取的信息进行筛选和替换的操作,
从而简化信息里多余的内容。
最后以上传文件是否包含在数据库信息中作为判断的条件来决定该上传文件是否有效
所以,“判断文件是否失效”的核心知识点还是对正则表达式的应用。
在动易网站中正则表达式的应用是比较多的,由此看出它在网站技术中的重要地位。
这里列出一篇文章《正则表达式的常用方法和属性以及应用举例》
http://blog.youkuaiyun.com/kof98cs/archive/2008/01/24/2063700.aspx
以便对正则表达式进行学习和复习
这篇文章我花一个星期左右的时间才写完,
主要是对该模块所用到的某些知识点和函数不熟,也因为懒所以知难而退
由于自己文笔不佳也写得语无伦次,
但通过自己在阅读时在模块文件中添加的注释可以很方便地查找某些细节代码。
所以想具体深入透彻了解此功能模块的朋友一定要亲自阅读以上几个模块文件的代码
不懂到知识点可以查找有关ASP和VBSscript的手册来学习,
尤其提高对FSO和正则表达式的运用能力。