导航

VBScript下载并执行FTP上的文件

Posted on 2012-09-23 09:56  moose  阅读(2935)  评论(0编辑  收藏  举报

代码更新: 2013/1/11

解决本地文件夹或文件名中有空格的问题

 


 

代码更新: 2012/9/25

去除ping小黑窗

优化代码结构


 

代码已更新  2012/9/24

下载全部文件

 


 

1. 程序只会下载含有关键字(forme)的文件   

2. 程序只会执行vbs 或者 bat类型的文件(如果需要可自行添加更多的文件支持)

3. 如果需要更新当前程序,新文件(ftp上的文件)需要包含关键字(syncftp)

4. 如果本地有同名文件,程序不会进行下载

5. 如果本地程序已执行过,则不会再次执行

6. 程序运行时会生成两个文件,一个是log文件,一个是配置文件

7. 如果需要定时执行,可以写为计划任务    

 

代码如下:

 

'***********************************************************************************
'*
'* File:		SyncVbs - FtpAndLocal
'* Author:		moose
'* Email:		852354673@qq.com
'* Site: www.pystack.org '* Created: 2012/9/10 '* Last Modified: 2012/9/20 '* Version: 0.3 '* '*********************************************************************************** Const secureKey = "U3luY1ZicyAtIEZ0cEFuZExvY2Fs" startTime = Now() currVbsName = WScript.ScriptName currVbsPath = WScript.ScriptFullName currVbsDir = Left(currVbsPath,InStrRev(currVbsPath,"\")) '生成日志文件 logFileName = "syncvbs.log" logFilePath = currVbsDir & logFileName Set fs = CreateObject("scripting.filesystemobject") Set ws = CreateObject("wscript.shell") Set logFileObject = fs.OpenTextFile(logFilePath,8,True) logFileObject.WriteLine "********************************** " &Now& " **********************************" '检查当前文件是否合法 If Not isALegalFile(currVbsName,secureKey) Then logFileObject.WriteLine Time & " Illegal file : " & currVbsName logFileObject.WriteBlankLines 4 logFileObject.Close WScript.Quit End If 'ftp相关配置 Const ftp_server = "192.168.8.123" Const ftp_user = "moose" Const ftp_password = "moose" Const ftp_remoteDir = "\" Const ftp_localDir = "D:\ftptest\" Const ftp_remoteFile = "*" Const ftp_configFile = "listfiles.ini" '生成本地文件列表 If "" = Trim(ftp_localDir) Then logFileObject.WriteLine Time & " Variable(ftp_localDir) is null..." logFileObject.WriteBlankLines 4 logFileObject.Close WScript.Quit End If localFileNamesStr = getLocalFileList(ftp_localDir) '检查网络是否连接 If "" = Trim(ftp_server) Then '如果远程IP为空,则退出程序 logFileObject.WriteLine Time & " Variable(ftp_server) is null..." logFileObject.WriteBlankLines 4 logFileObject.Close WScript.Quit End If If Not isFtpAccessable(ftp_server) Then '如果网络不连通,则退出程序 logFileObject.WriteLine Time & " Ip(" &ftp_server& ") is not accessable..." logFileObject.WriteBlankLines 4 logFileObject.Close WScript.Quit End If '生成远程ftp文件列表 If Trim(ftp_user) = "" Then ftp_user = "Anonymous" End If If Len(Trim(ftp_remoteDir)) = 0 Then ftp_remoteDir = "\" End If remoteFileNamesStr = getRemoteFileList(ftp_server,ftp_user,ftp_password,ftp_remoteDir) If "" = remoteFileNamesStr Then '如果远程文件为空,则退出程序 logFileObject.WriteLine Time & " No file in remote directory..." logFileObject.WriteBlankLines 4 logFileObject.Close WScript.Quit End If '检查远程文件是否与本地文件同名 unSameFileNameStr = removeSameFile(localFileNamesStr,remoteFileNamesStr) If "" = unSameFileNameStr Then '如果非同名文件为空,则退出程序 logFileObject.WriteLine Time & " No file need to be download..." logFileObject.WriteBlankLines 4 logFileObject.Close WScript.Quit End If '下载远程文件 downloadRemoteFile ftp_server,ftp_user,ftp_password,ftp_localDir,ftp_remoteDir,unSameFileNameStr '执行下载完毕的文件 executeFiles(unSameFileNameStr) '文件结束 logFileObject.WriteLine Time & " Done" logFileObject.WriteLine "Time used: " & DateDiff("s",startTime,Now) & "s" logFileObject.WriteBlankLines 4 logFileObject.Close '******************************************************************** '* '* Function updateThisFile(str_fileToUpdate) '* Purpose: 更新当前脚本 '* Input: str_fileToUpdate: 新脚本名称 '* Output: '* '******************************************************************** Function updateThisFile(str_fileToUpdatePath) fs.DeleteFile currVbsPath,True fs.MoveFile str_fileToUpdatePath,currVbsPath End Function '******************************************************************** '* '* Function executeFiles(str_filesPath) '* Purpose: 执行下载完的文件 '* Input: str_filesPath: 本地文件串 '* Output: True/False '* '******************************************************************** Function executeFiles(str_filesPath) logFileObject.WriteLine Time & " Executing files..." filesNeedToExec_obj = Split(str_filesPath,",") fileExecutedCount_int = 0 failToExecuteCount_int = 0 For Each fileToExec_str In filesNeedToExec_obj '获得文件后缀 fileType_str = Right(fileToExec_str,Len(fileToExec_str)-InStrRev(fileToExec_str,".")) fileType_str = Trim(LCase(fileType_str)) If InStr(fileType_str, "vbs")>0 Or InStr(fileType_str, "bat")>0 Then fileToExecPath_str = ftp_localDir & fileToExec_str 'WScript.Echo fileType_str & " : " & fileToExecPath_str 'WScript.Echo Asc(Right(fileToExecPath_str,1)) 'fileToExecPath_str = Left(fileToExecPath_str,Len(fileToExecPath_str)-1) '为什么要减1 'WScript.Echo fileToExecPath_str If fs.FileExists(fileToExecPath_str) Then If InStr(LCase(fileToExec_str),"syncvbs")>0 Then updateThisFile(fileToExecPath_str) else logFileObject.WriteLine Time & " Executing file (" &fileToExec_str& ")" fileToExecPath_str = """" &fileToExecPath_str& """" ws.Run fileToExecPath_str,0,True fileExecutedCount_int = fileExecutedCount_int + 1 logFileObject.WriteLine Time & " Done" End If Else logFileObject.WriteLine Time & " Error:File (" &fileToExec_str& ") not downloaded..." failToExecuteCount_int = failToExecuteCount_int + 1 End If End If Next logFileObject.WriteLine Time & " Executed(" &fileExecutedCount_int& ") Failed(" &failToExecuteCount_int& ")" logFileObject.WriteBlankLines 1 End Function '******************************************************************** '* '* Function downloadRemoteFile(str_server,str_user,str_password,str_localDir,str_remoteDir,str_remoteFiles) '* Purpose: 获得远程目录的文件列表 '* Input: str_server: 远程主机地址 '* str_user:ftp用户名 '* str_password:ftp密码 '* str_localDir:本地目录 '* str_remoteDir:远程目录 '* str_remoteFiles:待下载文件 '* Output: null '* '******************************************************************** Function downloadRemoteFile(str_server,str_user,str_password,str_localDir,str_remoteDir,str_remoteFiles) '如果需要下载的文件为空,则退出function If "" = str_remoteFiles Then logFileObject.WriteLine Time & " No file need to download..." Exit Function End If '处理路径中的空格 str_remoteDir = Trim(str_remoteDir) If InStr(str_remoteDir," ")>0 Then If Left(str_remoteDir,1)<> """" And Right(str_remoteDir,1) <> """" Then str_remoteDir = """" &str_remoteDir& """" End If End If '设置工作路径 originalWorkingDirectory = ws.CurrentDirectory ws.CurrentDirectory = str_localDir '生成ftp命令 ftpScript_str = "" ftpScript_str = ftpScript_str & "USER " & str_user & vbCrLf ftpScript_str = ftpScript_str & str_password & vbCrLf ftpScript_str = ftpScript_str & "cd " & str_remoteDir & vbCrLf ftpScript_str = ftpScript_str & "binary" & vbCrLf ftpScript_str = ftpScript_str & "prompt off" & vbCrLf remoteFiles_obj = Split(str_remoteFiles,",") For Each remoteFile_str In remoteFiles_obj 'remoteFile_str = Left(remoteFile_str,Len(remoteFile_str)-1) '去除回车符(为什么会有换行符?) If InStr(remoteFile_str, " ")>0 Then remoteFile_str = """" & remoteFile_str & """" End If ftpScript_str = ftpScript_str & "get " & remoteFile_str & vbCrLf Next ftpScript_str = ftpScript_str & "bye" & vbCrLf & "quit" & vbCrLf & "quit" & vbCrLf '创建临时文件 tempDir_str = ws.ExpandEnvironmentStrings("%TEMP%") scriptFilePath_str = tempDir_str& "\" &fs.GetTempName ftpResultPath_str = tempDir_str& "\" &fs.GetTempName '临时ftp脚本文件 Set scriptFile_obj = fs.OpenTextFile(scriptFilePath_str,2,True) scriptFile_obj.Write(ftpScript_str) scriptFile_obj.Close '执行ftp脚本 logFileObject.WriteLine Time & " Downloading files from ftp..." ws.Run "%comspec% /c FTP -n -s:" &""""&scriptFilePath_str&""""& " " &str_server& " > " &ftpResultPath_str,0,True WScript.Sleep 1000 '临时ftp结果文件 Set resultFile_obj = fs.OpenTextFile(ftpResultPath_str,1) successDownloadCount_int = 0 failToDownloadCount_int = 0 'WScript.Echo scriptFilePath_str & " " &ftpResultPath_str 'WScript.Echo ftpScript_str Do Until resultFile_obj.AtEndOfStream currLine_str = resultFile_obj.ReadLine 'WScript.Echo currLine_str ' If InStr(currLine_str,"get ")>0 And InStr(currLine_str,"forme")>0 Then If InStr(currLine_str,"get ")>0 Then currLine_str = Right(currLine_str,Len(currLine_str)-(InStr(currLine_str,"get ")+3)) nextLine_str = resultFile_obj.ReadLine nextLine_str = resultFile_obj.ReadLine nextLine_str = resultFile_obj.ReadLine If InStr(nextLine_str,"226 Transfer complete")>0 Then successDownloadCount_int = successDownloadCount_int + 1 logFileObject.WriteLine Time & " Finish downloading file(" &currLine_str& ")" Else failToDownloadCount_int = failToDownloadCount_int + 1 logFileObject.WriteLine Time & " Error:Fail to download file(" &currLine_str& ")" End If End If Loop resultFile_obj.Close logFileObject.WriteLine Time & " Complete(" &successDownloadCount_int& ") Failed(" &failToDownloadCount_int& ")" logFileObject.WriteBlankLines 1 End Function '******************************************************************** '* '* Function removeSameFile(Str_localFiles,str_removeFiles) '* Purpose: 去除远程文件列表和本地文件列表中相同的文件 '* Input: Str_localFiles: 本地文件串 '* str_removeFiles:远程文件串 '* Output: True/False '* '******************************************************************** Function removeSameFile(Str_localFiles,str_removeFiles) '如果本地文件列表为空,则退出function If "" = Trim(Str_localFiles) Then removeSameFile = str_removeFiles Exit Function End If unSameFileName_str = "" unSameFileCount_int = 0 saneFileCount = 0 remoteFiles_obj = Split(str_removeFiles,",") For Each remoteFile_str In remoteFiles_obj 'newremoteFile_str = Left(Trim(remoteFile_str),Len(remoteFile_str)-InStrRev(remoteFile_str,".")) '好奇怪的问题 If InStr(Str_localFiles,remoteFile_str) > 0 Then logFileObject.WriteLine Time & " File(" &remoteFile_str& ") has been downloaded..." saneFileCount = saneFileCount + 1 Else logFileObject.WriteLine Time & " File(" &remoteFile_str& ") need to download..." unSameFileName_str = unSameFileName_str & remoteFile_str & "," unSameFileCount_int = unSameFileCount_int + 1 End If Next logFileObject.WriteLine Time & " NeedTo Download(" &unSameFileCount_int& ") Has Downloaded(" &saneFileCount& ")" logFileObject.WriteBlankLines 1 '去除最后一个逗号 If Not "" = Trim(unSameFileName_str) Then unSameFileName_str = Left(unSameFileName_str,Len(unSameFileName_str)-1) End If '返回文件列表字符串 removeSameFile = unSameFileName_str End Function '******************************************************************** '* '* Function getRemoteFileList(str_server,str_user,str_password,str_remoteDir) '* Purpose: 获得远程目录的文件列表 '* Input: str_server: 远程主机地址 '* str_user:ftp用户名 '* str_password:ftp密码 '* str_remoteDir:远程目录 '* Output: 文件字符串 '* '******************************************************************** Function getRemoteFileList(str_server,str_user,str_password,str_remoteDir) '处理含有空格的路径,加上引号 str_remoteDir = Trim(str_remoteDir) If InStr(str_remoteDir," ")>0 Then If Left(str_remoteDir,1)<> """" And Right(str_remoteDir,1) <> """" Then str_remoteDir = """" &str_remoteDir& """" End If End If '查看配置文件是否存在,不存在则创建 fileListScriptConfigPath_str = currVbsDir & ftp_configFile If Not fs.FileExists(fileListScriptConfigPath_str) Then logFileObject.WriteLine Time & " Generate file(" &ftp_configFile& ")" Set fileListScriptFile_obj = fs.OpenTextFile(fileListScriptConfigPath_str,2,True) fileListScriptFile_obj.WriteLine "USER " & str_user fileListScriptFile_obj.WriteLine str_password fileListScriptFile_obj.WriteLine "cd " & str_remoteDir fileListScriptFile_obj.WriteLine "ls" fileListScriptFile_obj.WriteLine "bye" fileListScriptFile_obj.WriteLine "quit" fileListScriptFile_obj.WriteLine "quit" fileListScriptFile_obj.Close logFileObject.WriteLine Time & " Done" logFileObject.WriteBlankLines 1 End If logFileObject.WriteLine Time & " Generating remote file list..." '创建临时文件 tmpDir_str = ws.ExpandEnvironmentStrings("%TEMP%") tmpFilePath_str = tmpDir_str& "\" &fs.GetTempName ws.Run "%comspec% /c FTP -n -s:" &"""" &fileListScriptConfigPath_str& """"& " " &str_server& " > " &tmpFilePath_str,0,True '读取文件,得到文件列表 '***********************V1************************** ' Set tempFile_obj = fs.OpenTextFile(tmpFilePath_str,1) ' remoteFiles_str = "" ' needToBeDownload_int = 0 ' Do Until tempFile_obj.AtEndOfStream ' tempLine_str = tempFile_obj.ReadLine ' If InStr(tempLine_str,"forme")>0 Then '只下载forme文件 ' remoteFiles_str = remoteFiles_str & tempLine_str & "," ' needToBeDownload_int = needToBeDownload_int + 1 ' End If ' Loop ' tempFile_obj.Close '***********************V1 end*********************** '***********************V2************************** '找出文件开始行和结束行 remoteFiles_str = "" Set tempFile_obj = fs.OpenTextFile(tmpFilePath_str,1) currentLine_int = 1 startLine_int = 0 endLine_int = 0 Do Until tempFile_obj.AtEndOfStream tempLine_str = tempFile_obj.ReadLine If InStr(tempLine_str,"150") Then startLine_int = currentLine_int ElseIf InStr(tempLine_str,"226") Then endLine_int = currentLine_int Else currentLine_int = currentLine_int + 1 End If Loop tempFile_obj.Close If endLine_int < startLine_int Then logFileObject.WriteLine Time & " (EndLine < StartLine) No file will download..." getRemoteFileList = remoteFiles_str Exit Function End If 'WScript.Echo endLine_int & startLine_int '得到文件列表字符串 Set tempFile_obj = fs.OpenTextFile(tmpFilePath_str,1) currentLine_int = 0 Do Until tempFile_obj.AtEndOfStream currLine_str = tempFile_obj.ReadLine currentLine_int = currentLine_int + 1 If currentLine_int > startLine_int And currentLine_int <= endLine_int Then currLine_str = Left(currLine_str,Len(currLine_str)-1) remoteFiles_str = remoteFiles_str & currLine_str & "," End If Loop tempFile_obj.Close 'WScript.Echo remoteFiles_str 'WScript.Echo tmpFilePath_str '***********************V2 end*********************** logFileObject.WriteLine Time & " There " & endLine_int - startLine_int & " files in remote directory" logFileObject.WriteBlankLines 1 '去除最后一个逗号 If Not "" = Trim(remoteFiles_str) Then remoteFiles_str = Left(remoteFiles_str,Len(remoteFiles_str)-1) End If '返回文件列表字符串 getRemoteFileList = remoteFiles_str End Function '******************************************************************** '* '* Function isFtpAccessable(ip_str) '* Purpose: 检查网络是否连通 '* Input: str_ipaddr: 远程ftp IP地址 '* Output: True/False '* '******************************************************************** Function isFtpAccessable(str_ipaddr) tmpDir_str = ws.ExpandEnvironmentStrings("%TEMP%") tmpFilePath_str = tmpDir_str& "\" &fs.GetTempName connand_str = "%comspec% /c ping " & str_ipaddr & " >"&tmpFilePath_str '**********************V1********************** '会弹出小黑窗 ' Set pingResult_obj = ws.Exec(connand_str) ' result_str = pingResult_obj.StdOut.ReadAll '**********************V1 end****************** '**********************V2********************** '取消小黑窗 ws.Run connand_str,0,True Set tmpFile_obj = fs.OpenTextFile(tmpFilePath_str,1) result_str = tmpFile_obj.ReadAll tmpFile_obj.Close '**********************V2 end****************** If InStr(result_str,"Minimum")>0 Or InStr(result_str,"最长")>0 Then isFtpAccessable = True Else isFtpAccessable = False End If End Function '******************************************************************** '* '* Function getLocalFileList(str_localDir) '* Purpose: 获得本地目录的文件列表 '* Input: str_localDir: 本地目录 '* Output: 文件字符串 '* '******************************************************************** Function getLocalFileList(str_localDir) '如果目录不存在,则新建目录 If Not fs.FolderExists(str_localDir) Then logFileObject.WriteLine Time & " Folder (" &str_localDir& ") not exist..." fs.CreateFolder(str_localDir) logFileObject.WriteLine Time & " Finish creating folder (" &str_localDir& ")" getLocalFileList = "" Exit Function End If localFileNames_str = "" LocalFileCount = 0 Set localDir_obj = fs.GetFolder(str_localDir) For Each localFile_obj In localDir_obj.Files LocalFileCount = LocalFileCount + 1 localFileNames_str = localFileNames_str & localFile_obj.Name & "," Next '去除最后一个,号 If Not localFileNames_str = "" Then localFileNames_str = Left(localFileNames_str,Len(localFileNames_str)-1) End If logFileObject.WriteLine Time & " LocalFile (Total: " &LocalFileCount& ") " &localFileNames_str logFileObject.WriteBlankLines 1 getLocalFileList = localFileNames_str End Function '******************************************************************** '* '* Function isALegalFile(str_vbsName,str_secureKey) '* Purpose: 检查文件是否合法 '* Input: str_vbsName: vbs文件名 '* str_secureKey:验证字符 '* Output: True/False '* '******************************************************************** Function isALegalFile(str_vbsName,str_secureKey) If base64Encode(str_vbsName) = str_secureKey Then isALegalFile = True Else isALegalFile = False End If End Function '******************************************************************** '* '* Function Base64Encode(str_filename) '* Purpose: 根据文件名生成校验字符 '* Input: str_filename '* Output: 校验字符 '* '******************************************************************** Function base64Encode(str_filename) Const Base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" Dim cOut, sOut, I For I = 1 To Len(str_filename) Step 3 Dim nGroup, pOut, sGroup nGroup = &H10000 * Asc(Mid(str_filename, I, 1)) + _ &H100 * MyASC(Mid(str_filename, I + 1, 1)) + MyASC(Mid(str_filename, I + 2, 1)) nGroup = Oct(nGroup) nGroup = String(8 - Len(nGroup), "0") & nGroup pOut = Mid(Base64, CLng(" &o" & Mid(nGroup, 1, 2)) + 1, 1) + _ Mid(Base64, CLng(" &o" & Mid(nGroup, 3, 2)) + 1, 1) + _ Mid(Base64, CLng(" &o" & Mid(nGroup, 5, 2)) + 1, 1) + _ Mid(Base64, CLng(" &o" & Mid(nGroup, 7, 2)) + 1, 1) sOut = sOut + pOut Next Select Case Len(str_filename) Mod 3 Case 1: '8 bit final sOut = Left(sOut, Len(sOut) - 2) + "==" Case 2: '16 bit final sOut = Left(sOut, Len(sOut) - 1) + "=" End Select Base64Encode = sOut End Function Function MyASC(OneChar) If OneChar = "" Then MyASC = 0 Else MyASC = Asc(OneChar) End Function