铁匠

做人要低调
随笔 - 134, 评论 - 255 , 引用 - 184

导航

公告

文章分类

存档

随笔分类

相册

BLOG

网站

论坛

新闻系统里防止产生垃圾图片的一种方法

现在的新闻系统里越多地支持在线上传插入图片,以实现在比较好的效果。可是问题也随之而来了,有的图片传上去后,发现这个图片不对,那只能在编辑器里把它删掉,或是,在添加地程中系统出现问题,而导致垃圾图片的产生。为了防止在这过程中出现垃圾图片和附件,许多人多研究了不少的方法,如动网论坛里,对上传的每一个文件,在数据库里都有相应的一个记录,这样要占用一个表来存放,并且如果在添加数据到数据库里时系统出现异常,也同样无法避免这些垃圾的产生。经过我的一些实践,研究出我的方法,现在贡献出来,供大家斧正。
我的方法流程是这样的:当文章的添加者登录到系统里面后,由系统给它创建一个临时的工作文件夹,如“editor”这个用户的ID是5那我建立一个temp5的临时工作目录,当他添加文章的时候,上传的图片和其它附件并不存入到真正要显示存放的目录,而是存在这个临时的工作目录里面。同时为了方便管理,我建议给每一条新闻建一个目录来存放这些图片,当文章提交的时候,由系统分析里面的图片地址,把文章里面有的图片转移到这些对应的目录里面去。当新闻或文章改动的时候,就先把这个文件夹下面的所有图片转移到进入的时候的临时工作目录里面,同时对文章里面的图片路径进行替换,保存的时候也是和添加的时候执行同一个过程。当文章删除的时候,也相对应地把这个目录删掉,这就可以保证了在添加、修改、删除的过程中没有垃圾图片的产生。当用户登出的时候,系统可以将其所对应的工作目录删除,这样就可以彻底地作到没有垃圾的产生。
看到上面这些文字描述也许好多人要头晕了,那看一下具体的实现过程吧(因为我对ASP比较熟悉,所以我用ASP来实现它了,用其它的平台也是可以实现的)。首先让我先引入我自己写的一个类,用来分析和转移图片的,详细的说明请看我的另一篇文章:用asp自动解析网页中的图片地址,并将其保存到本地服务器(http://www.csdn.net/develop/read_article.asp?id=15585)
class blacksmith
'The Class "blacksmith" is Created by Linzhang Chen
'It could use for copy images form other server which contain in the web
dim size,baseurl,basefilename,tofolder,servername,processstr,firstoldimg,firstnewimg
?public Function saveimage(from, tofile)
?Dim geturl, objStream, imgs,s
?If size = "" Then
?size = 0
?End If
?geturl = Trim(from)
?imgs = getHTTPPage(geturl)
?s = size * 512
?If Len(imgs) > s Then
?Set objStream = CreateObject("ADODB.Stream")
?objStream.Type = 1
?objStream.Open
?objStream.Write imgs
?objStream.SaveToFile tofile, 2
?objStream.Close
?Set objStream = Nothing
?saveimage = True
?Else
?saveimage = False
?End If
?End Function

?private Function getHTTPPage(url)
?On Error Resume Next
?Dim http
?Set http = CreateObject("MSXML2.XMLHTTP")
?http.Open "GET", url, False
?http.send
?If http.readyState <> 4 Then
?Exit Function
?End If
?getHTTPPage = http.responseBody
?Set http = Nothing
?If Err.Number <> 0 Then Err.Clear
?End Function

?private Function getimgs(str)
?getimgs = ""
?Set objRegExp1 = New RegExp
?objRegExp1.IgnoreCase = True
?objRegExp1.Global = True
?objRegExp1.Pattern = "http://.+?"""
?Set mm = objRegExp1.Execute(str)
? For Each Match1 In mm
?getimgs = getimgs & "||" & Left(Match1.Value, Len(Match1.Value) - 1)
?Next
?End Function

?Function str2img()
?Dim servername, objRegExp, strs, Matches, RetStr, arrimg, newimg, i, fname, states, arrnew, arrall
?if baseurl<>"" then
??If Right(baseurl, 1) <> "/" Then
??baseurl = baseurl & "/"
??End If
?end if
?if right(tofolder,1)<>"\" then
?tofolder=tofolder&"\"
?end if
?Set objRegExp = New RegExp
?objRegExp.IgnoreCase = True
?objRegExp.Global = True
?objRegExp.Pattern = ""
?strs = Trim(processstr)
?Set Matches = objRegExp.Execute(strs)
?For Each Match In Matches
??RetStr = RetStr & getimgs(Match.Value)
?Next
?arrimg = Split(RetStr, "||")
?allimg = ""
?newimg = ""
?For i = 1 To UBound(arrimg)
??If arrimg(i) <> "" And InStr(allimg, arrimg(i)) < 1 Then
??fname1 = baseurl & CStr(basefilename & i & Mid(arrimg(i), InStrRev(arrimg(i), ".")))
??fname = tofolder & CStr(basefilename & i & Mid(arrimg(i), InStrRev(arrimg(i), ".")))
??states = saveimage(arrimg(i), fname)
???If states = True Then
???allimg = allimg & "||" & arrimg(i)
???newimg = newimg & "||" & fname1
???End If
??End If
?Next
?arrnew = Split(newimg, "||")
?arrall = Split(allimg, "||")
?For i = 1 To UBound(arrnew)
?if i=1 then
?firstoldimg=arrall(1)
?firstnewimg=arrnew(1)
?end if
?strs = Replace(strs, arrall(i), arrnew(i))
?Next
?str2img = strs
?End Function
end class
第一步用户登录的时候:由于有一个工作区,所以最好不要让多个用户用同一个帐号不然到时候有人登出的时候,将会造成其它人的工作丢失,这里最主要处理的是帐户登录的时候要对这个帐号锁定不允许重复登录(主要由FSO和数据库来实现,我就不多说了)。
在处理文件上传的时候,可以用稻香老农的无组件上传,把图片传到工作区中。并且把图片代码返回到编辑器中,当提交以后,将由以下代码来处理这些图片,我这里是根据新闻或文章的ID来创建文件夹的:
sql="select top 1 form news where id is null"
set rs=server.createobject("adodb.recordset")
rs.open sql,conn,1,3
rs.addnew
rs("userid")=session("myid")'因为是新加的,所以先加上一条来取得ID
rs.update
newID=rs("newsid")'大部分情况下,这样可以取得ID的,可是为了保险起见,所以最好还是再判断一下了
rs.close
set rs=nothing
if newsID="" then
set rs=conn.execute("select top 1 newsid from news where userid=" & session("myid") & " order by newsid desc")
newsID=rs("newsid")
end if

basefoder=server.mappath("photo")'假设图片存到当前目录下面的photo里面
set fso=Server.CreateObject("Scripting.FileSystemObject")
FiLePaTh = basefoder&"/"&newsID
Fso.Createfolder(FiLePaTh)
'假设将取得新闻的内容存在变量content里面下面就调用我的那个类blacksmith来处理分析文章的内容,处理图片的转移了
set bs=new blacksmith
bs.size=1
bs.baseurl="photo/"&newsID'给图片加上目录的地址
bs.basefilename="mynews"'给图片加上前缀
bs.servername = ""
bs.tofolder=FiLePaTh
bs.processstr=content
content=bs.str2img
set bs=nothing
'接下来就是新闻内容的保存的过程了,我这里就省去了,和其它的系统应该是一样的了

在处理新闻的修改的时候用:
'创建工作目录
set fso=Server.CreateObject("Scripting.FileSystemObject")
FiLePaTh = server.mappath("temp"&session("myid"))
If Not FSO.FolderExists(FiLePaTh) Then
Fso.Createfolder(FiLePaTh)
End If

FiLePaTh = basefoder&"/"&newsID
If? FSO.FolderExists(fp) Then
on error resume next
fso.copyfile fp&"\*.*",FiLePaTh&"\"'把那个目录下面的所有文件全拷到工作目录下面,防止出现修改了不保存,所以先不删除原有的内容
if err.num>0 then err.clear
End If
set fso=nothing
end if
'把原有的文件内容进行处理,改变里面的图片路径,比如说这此内容还是保存在content里面
content=replace(trim(content,"photo/"&newsID&"/mynews","temp"&session("myid")&"/mynews")'这个只是一个比较简单的替换,相信由此引起误替换的机会应该是相当小的了
保存的过程和添加的过程是一样的,所不同的是,要先把原来的那个目录里面的文件清空,我这里就不多说了。
新闻删除的时候,要记着把这个ID相对应的文件夹删除了,在用户登出的时候,也要把它的工作目录清空。
好了,我的整个思路就是这样的了,说不上是什么精品,但是它在实际的应用中,一年下来并没有产生过任何的意常,所以我就把它贴出来了,欢迎大家和我交流:E_mail:clzwin@sina.com

发表于 2004年4月4日 20:08

评论

# re: 新闻系统里防止产生垃圾图片的一种方法

我晕.

如果网速慢,会导致整个工作缓慢,可能会出现中途断掉的情况.那岂不是更累赘?

或者在修改过程中只打开了.没有保存就直接关闭.那怎么办?

另外,在大内容上传的时候,比如200K.很多系统本身就要处理内部很多的工作.本身就很浪费资源.再这么一搞.估计会更慢.

WEB项目.讲求的是效率和速度.
2006-8-12 23:08 | waner

# re: 新闻系统里防止产生垃圾图片的一种方法

事实上我当时写这个文章的时候,主要是针对于企业网来说的.因为很多的大中型网站,他们的服务器会放在他们的局域网里面,所以网速都不是问题.而且在里面说到的文件拷贝,都是在同一个服务器上完成的.
而且文章的添加和修改这些工作,对于个服务器的负载来说是很小的一个部分.
2006-8-14 11:12 | 铁匠

# re: 新闻系统里防止产生垃圾图片的一种方法

或者在修改过程中只打开了.没有保存就直接关闭.那怎么办?
---------
因为打开的时候,是把数据放到临时工作区去了,所以不保存也无所谓了.

如果网速慢,会导致整个工作缓慢,可能会出现中途断掉的情况.那岂不是更累赘?
---------
同一个服务器上的东西,应该不会存在掉线的情况


另外,在大内容上传的时候,比如200K.很多系统本身就要处理内部很多的工作.本身就很浪费资源.再这么一搞.估计会更慢.
------------
200K也算大内容?200K的数据对于服务器处理来说,只是用几个毫秒就完成了.
2006-8-14 11:15 | 铁匠

Post Comment

主题  
姓名  
主页
校验码  
内容   
京ICP备 05050892号