ftp automation

ScriptFTP

The professional tool to automate FTP, SFTP, FTPS and schedule FTP batch jobs

The forum is now read only. Please, go to the the main ScriptFTP website if you need help.
Need help writing a script? Have any question about ScriptFTP?
I have a remote camera which will FTP videos to a server (motion detection). However the up connection is slow. So if there is a lot of video files to upload, some of them get lost as the camera does not buffer. I can see this in the camera's log files as failed FTP uploads.

So I would like to set up a laptop which will have an FTP server installed (probably FileZilla's server). The camera will then FTP the files over a 100M connection to the laptop. I then want the laptop to FTP the files to my Internet server and delete them locally.

I know I can set up a script to wake up every so often and upload files, then delete them locally, but what if the camera is still busy sending a file which the script wants to upload? I would then get a partial file which could potentially be deleted.

Is there a way to tell if a file is in the process of being written to? So I can iterate over a list of files and only upload ones which are complete?
You can start with a very commonly used script called upload_and_delete.ftp available in the script library section of this website. I will paste it the most interesting part here (with some modifications):
FTP Script
  1. # Change current lcoal directory to where the videos are stored
  2. LOCALCHDIR("C:\camera_videos")
  3.  
  4. # Get the list of video files in that folder
  5. $result=GETLIST($list,LOCAL_FILES,"*.avi")
  6.  
  7. # For each video file in $list...
  8. FOREACH $item IN $list
  9.     # Upload the file
  10.     $result=PUTFILE($item)
  11.     # If the video file has been succesfully uploaded
  12.     # delete the local copy of the file
  13.     IF($result=="OK")
  14.         EXEC("del ".$item)
  15.     END IF

The problem could be, as you already point, that if the video file being uploaded by ScriptFTP is at the same time being sent from the camera... a corrupt or incomplete video file will be uploaded. Fortunately, I think that FileZilla server only actually stores the uploaded files once they are complately received, so ScriptFTP will not find incomplete files in the directory where the camera uploads its videos.
It is entirely possible to upload a partial file.

But I have come up with a script which should work. It relies on the OS file system "move" command. Since the file is open for a write operation is has an active file handle. So you cannot move it.

The script tries to move any files to a transfer directory, then uploads those files in the transfer directory. Any partial files will be handled during the next pass.

I have the script if you are willing to review it, plus you can put it into your script library if you wish.
That would be very interesting. Could you send me the script to scriptftp@scriptftp.com

Thanks.
wow, nice script Bucket. I will post it here, people usually visit the script library section only for very basic things and this one is a bit specific:
FTP Script
  1. # This script will upload video and picture files
  2.  
  3. SILENT(ON)
  4.  
  5. # Global Variables
  6. $UploadServer = "xxxx"
  7. $LocalFTPDir = "D:\FTP"
  8. $LocalUploadDir = "D:\Upload"
  9.  
  10. # in seconds
  11. $CycleDelay = 20
  12.  
  13. $LogDate = ""
  14.  
  15. # processing loop
  16. :aprocessingLoop
  17.     IF ($LogDate != GETTIME(YEAR)."-".GETTIME(MONTH)."-".GETTIME(DAY) )
  18.         if ( $LogDate != "" )
  19.             STOPLOG()
  20.         end if
  21.        
  22.         $LogDate = GETTIME(YEAR)."-".GETTIME(MONTH)."-".GETTIME(DAY)
  23.         LOGTO($LocalUploadDir."\Logs\".$LogDate.".txt",APPEND)
  24.         SILENT(ON)
  25.  
  26.         PRINT("**************************************************************")
  27.         PRINT("File Open ".GETTIME(YEAR).".".GETTIME(MONTH).".".GETTIME(DAY)." ".GETTIME(HOUR).":".GETTIME(MIN).":".GETTIME(SEC))
  28.     END IF
  29.    
  30.     Print("Waiting ".$CycleDelay." seconds")
  31.     Sleep($CycleDelay)
  32.  
  33.     PRINT("Start ".GETTIME(YEAR).".".GETTIME(MONTH).".".GETTIME(DAY)." ".GETTIME(HOUR).":".GETTIME(MIN).":".GETTIME(SEC))
  34.     $StartTimestamp=GETTIME(FORMAT0)
  35.  
  36.     # process GH
  37.     $return = 1
  38.     $localDir = "GH"
  39.     $userName = "xxxx"
  40.     $password = "xxxx"
  41.  
  42.     goto :aprocessFiles
  43.  
  44. :Return1
  45.  
  46.     # process Cabin
  47.     $return = 2
  48.     $localDir = "Cabin"
  49.     $userName = "xxxx"
  50.     $password = "xxxx"
  51.  
  52.     goto :aprocessFiles
  53.  
  54. :Return2
  55.  
  56. :Cycle
  57.  
  58.     PRINT("End ".GETTIME(YEAR).".".GETTIME(MONTH).".".GETTIME(DAY)." ".GETTIME(HOUR).":".GETTIME(MIN).":".GETTIME(SEC))
  59. goto :aprocessingLoop
  60.  
  61. # ########################################################
  62. # ########################################################
  63.  
  64. # the basic operation is:
  65. #  1. Move any files from the camera inbound FTP directory to the
  66. #     associated upload directory
  67. #  2. Upload any files in the upload directory to the remote server
  68. #  3. Delete uploaded files in the upload directory
  69. #  4. Rinse, wash, repeat
  70.  
  71. :aprocessFiles
  72.  
  73. PRINT("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -")
  74.  
  75. $sourceDir = $LocalFTPDir."\".$localDir
  76. $targetDir = $LocalUploadDir."\".$localDir
  77.  
  78. Print("- Processing: ".$sourceDir)
  79.  
  80. # ------------------
  81. #first move any file from the FTP dir to the upload dir
  82. $result = Localchdir($sourceDir)
  83.  
  84. IF ($result != "OK")
  85.     Print("- Failed to change to local source directory: ".$sourceDir)
  86.     goto :ReturnBlock
  87.  
  88. $result = Getlist($fileList,LOCAL_FILES)
  89.  
  90. IF ($result != "OK")
  91.     goto :ReturnBlock
  92.  
  93. $moveCount = 0
  94. $totalCount = 0
  95.  
  96. FOREACH $fileName IN $fileList
  97.     $fullFileName = $sourceDir."\".$fileName
  98.  
  99.     $totalCount = $totalCount + 1
  100.  
  101.     # if this fails, then the file is still being written to
  102.     $result = Exec("move ".$fullFileName." ".$targetDir)
  103.  
  104.     if($result == 0 )
  105.         $moveCount = $moveCount + 1
  106.     else
  107.         print("- Failed to Move ".$fullFileName." to ".$targetDir)
  108.         Print("- - Error code: ".$result)
  109.     end if
  110.  
  111. print("- Moved ".$moveCount." of ".$totalCount)
  112.  
  113. # ------------------
  114. # Upload the moved files to the remote server
  115.  
  116. $result = Localchdir($targetDir)
  117.  
  118. IF ($result != "OK")
  119.     Print("- Failed to change to local target directory: ".$targetDir)
  120.     goto :ReturnBlock
  121.  
  122. $result = Getlist($fileList,LOCAL_FILES)
  123.  
  124. IF ($result != "OK")
  125.     goto :ReturnBlock
  126.  
  127. IF (COUNTELEMENTS($fileList) == 0 )
  128.     goto :ReturnBlock
  129.  
  130. $result = Openhost($UploadServer,$userName,$password)
  131.  
  132. IF ($result != "OK")
  133.     Print("- Failed to log into the FTP host ".$UploadServer." for ".$localDir)
  134.     goto :ReturnBlock
  135.  
  136. Setpassive(ENABLED)
  137.  
  138. $uploadCount = 0
  139. $deleteCount = 0
  140. $totalCount = 0
  141.  
  142. FOREACH $fileName IN $fileList
  143.     $fullFileName = $targetDir."\".$fileName
  144.  
  145.     $result = Putfile($fileName)
  146.  
  147.     $totalCount = $totalCount + 1
  148.  
  149.     IF($result == "OK")
  150.         $uploadCount = $uploadCount + 1
  151.  
  152.         $result = Exec("del ".$fullFileName)
  153.  
  154.         IF ($result == 0 )
  155.             $deleteCount = $deleteCount + 1
  156.         ELSE
  157.             Print("- Failed to delete ".$fullFileName)
  158.             Print("- - Error code: ".$result)
  159.         END IF
  160.     ELSE
  161.         Print("- Failed to upload ".$fullFileName)
  162.     END IF
  163.  
  164.  
  165. print("- Uploaded ".$uploadCount." of ".$totalCount)
  166. print("- Deleted ".$deleteCount." of ".$totalCount)
  167.  
  168. # ------------------
  169. # Now go back
  170. :ReturnBlock
  171.  
  172. # just in case it is open when we get here (ie: via an error)
  173. if ( ISCONNECTED() == "TRUE" )
  174.     Closehost
  175.  
  176. IF ($return == 1)
  177.     goto :Return1
  178.  
  179. IF ($return == 2)
  180.     goto :Return2
  181.  
  182. Print("- Unknown return code: ".$return)
  183. goto :Cycle
  184.  
  185. # ########################################################
  186. # ########################################################
:ProcessingLoop as <img src="./images/smilies/icon_razz.gif" alt=":P" title="Razz" />rocessingLoop has pleased. In section [ScriptFTP] it is necessary smilies and other options should not work.
Hi Wandrey,

I've just fixed it replacing the labels in the script.

The script syntax highlighter that runs behind the forum still looks for smilies in the scripts...
Just as a point of interest, the camera takes less than a second to xfer a file to the computer over the 100MBps connection. The script then moves the file from the FTP directory to the Upload directory, and this also takes less than a second.

And I already had a conflict between the two operations, that split second timing when the stars aligned. The script worked as designed and the offending file was uploaded during the next cycle.

Secondly there was a connection failure (timeout) connecting to the Internet FTP server. Normally this would have resulted in a lost file, but the script re-connected at the next cycle and uploaded the file.
Thanks for the update and your collaboration Bucket