我写过不少定时上传的定代码脚本,最头疼的时上就是ASP环境下的文件处理。别急着找现成代码,传文先想清楚你的定代码场景:是定时把本地文件推到服务器,还是时上服务器之间同步?我遇到的大多数需求,其实是传文第二种——比如每天凌晨把生成好的报表传到另一台机器上。
ASP没有内置的定代码定时器,得靠外部触发。时上最土的传文办法是写个死循环页面,用`Server.ScriptTimeout`把超时设长,定代码再配合`Application.Lock`防止并发。时上但这样太耗资源,传文IIS会疯掉的定代码。实际项目里我都是时上靠Windows计划任务调一个隐藏页面,或者用数据库里的传文任务表轮询。
核心代码其实就三块:获取文件、建立FTP连接、上传。看这段——
<% Dim fso, fileStream, ftpConn Set fso = Server.CreateObject("Scripting.FileSystemObject") Set fileStream = fso.OpenTextFile("C:\data\report.txt", 1) Set ftpConn = Server.CreateObject("MSXML2.ServerXMLHTTP") ftpConn.open "PUT", "ftp://user:pass@192.168.1.10/upload/report.txt", False ftpConn.send fileStream.ReadAll fileStream.Close Set fileStream = Nothing Set fso = Nothing %> 别高兴太早,这段代码有个坑——`MSXML2.ServerXMLHTTP`对FTP协议支持并不完美,尤其碰到需要被动模式的服务器就歇菜。我踩过这坑,最后改用`WinHTTP.WinHTTPRequest.5.1`对象,稳定性好很多。要是嫌麻烦,直接调系统自带的`ftp.exe`命令行也行,但那样得小心处理密码明文暴露的问题。
定时这部分,我习惯在数据库里存一张任务表,字段就三个:`task_name`、`next_run_time`、`file_path`。然后写个ASP页面专门检查当前时间有没有到点的任务,到了就执行上传,执行完把`next_run_time`往后推一天。计划任务每五分钟打一次这个页面,IIS那边记得把该页面的匿名访问关掉,不然谁都能触发你的上传逻辑。
文件命名得留个心眼。我见过有人直接用`now()`拼文件名,结果冒号把Windows路径搞炸了。稳妥做法是`Year(Now()) & Month(Now()) & Day(Now()) & Hour(Now()) & Minute(Now())`,生成类似`202503171030`这样的纯数字串。
上传完别忘了校验文件大小。FTP传输经常断在半路,服务器上留个残缺文件最坑人。我一般先传临时名,传完再改名。代码里加几行:
<% ' 先传成 .tmp ftpConn.open "PUT", "ftp://.../report.tmp", False ' 上传成功后执行改名命令 ftpConn.open "RNFR", "ftp://.../report.tmp", False ftpConn.open "RNTO", "ftp://.../report_" & fileStamp & ".txt", False %> 实际跑起来你会发现,ASP处理FTP超时特别让人抓狂。默认60秒,大文件肯定不够。得在页面开头写`Server.ScriptTimeout = 300`,但IIS的`AspScriptTimeout`元数据库设置也得同步调,不然还是被掐断。我吃过这个亏,调了一下午才发现是两套超时机制在打架。
最后说个冷门的——如果你服务器开了防火墙,记得放行FTP的数据端口。主动模式用20端口,被动模式端口范围不定,最省事的是直接在代码里固定被动模式,然后只开一个端口段。别问我怎么知道的,都是泪。
这套东西虽然土,但胜在逻辑直白,出问题好排查。真要追求优雅,不如换.NET或Python写Windows服务,不过那就超出ASP的范畴了。

喜欢
讨厌