Link to home
Start Free TrialLog in
Avatar of Mik Mak
Mik Mak

asked on

FTP upload - rename file after upload

I've found this function that I use for uploading a database file to a FTP server, and it works fine. But I need to have an additional parameter in the function, so that after uploading the file to the folder indicated by the sDir paramter, it checks if a new parameter sDirRen is diffenrent from sDir, and if it is, it renames the file on the ftp server.

similar to the FTP command: "ren sDir/filename sDirRen/filename"

Can someone please help me with this modification to the  function shown below :) ?

Function FTPFile(ByVal HostName As String, _
    ByVal UserName As String, _
    ByVal Password As String, _
    ByVal LocalFileName As String, _
    ByVal RemoteFileName As String, _
    ByVal sDir As String, _
    ByVal sMode As String) As Boolean
   
    On Error GoTo Err_Function
       
' Declare variables
Dim hConnection, hOpen, hFile  As Long ' Used For Handles
Dim iSize As Long ' Size of file for upload
Dim Retval As Variant ' Used for progress meter
Dim iWritten As Long ' Used by InternetWriteFile to report bytes uploaded
Dim iLoop As Long ' Loop for uploading chuncks
Dim iFile As Integer ' Used for Local file handle
Dim FileData(BUFFER_SIZE - 1) As Byte ' buffer array of BUFFER_SIZE (100) elements 0 to 99

' Open Internet Connecion
hOpen = InternetOpen("FTP", 1, "", vbNullString, 0)

' Connect to FTP
hConnection = InternetConnect(hOpen, HostName, INTERNET_DEFAULT_FTP_PORT, UserName, Password, INTERNET_SERVICE_FTP, IIf(PassiveConnection, INTERNET_FLAG_PASSIVE, 0), 0)

' Change Directory
Call FtpSetCurrentDirectory(hConnection, sDir)

' Open Remote File
hFile = FtpOpenFile(hConnection, RemoteFileName, GENERIC_WRITE, IIf(sMode = "Binary", FTP_TRANSFER_TYPE_BINARY, FTP_TRANSFER_TYPE_ASCII), 0)

' Check for successfull file handle
If hFile = 0 Then
    MsgBox "Internet - Failed!"
    ShowError
    FTPFile = False
    GoTo Exit_Function
End If

' Set Upload Flag to True
FTPFile = True

' Get next file handle number
iFile = FreeFile

' Open local file
Open LocalFileName For Binary Access Read As iFile

' Set file size
iSize = LOF(iFile)

' Iinitialise progress meter
Retval = SysCmd(acSysCmdInitMeter, "Uploading File (" & RemoteFileName & ")", iSize / 1000)

' Loop file size
For iLoop = 1 To iSize \ BUFFER_SIZE
       
    ' Update progress meter
    Retval = SysCmd(acSysCmdUpdateMeter, (BUFFER_SIZE * iLoop) / 1000)
       
    'Get file data
    Get iFile, , FileData
     
    ' Write chunk to FTP checking for success
    If InternetWriteFile(hFile, FileData(0), BUFFER_SIZE, iWritten) = 0 Then
        MsgBox "Upload - Failed!"
        ShowError
        FTPFile = False
       GoTo Exit_Function
    Else
        ' Check buffer was written
        If iWritten <> BUFFER_SIZE Then
            MsgBox "Upload - Failed!"
            ShowError
            FTPFile = False
            GoTo Exit_Function
        End If
    End If
   
Next iLoop

' Handle remainder using MOD

    ' Update progress meter
    Retval = SysCmd(acSysCmdUpdateMeter, iSize / 1000)

    ' Get file data
    Get iFile, , FileData
   
    ' Write remainder to FTP checking for success
    If InternetWriteFile(hFile, FileData(0), iSize Mod BUFFER_SIZE, iWritten) = 0 Then
        MsgBox "Upload - Failed!"
        ShowError
        FTPFile = False
        GoTo Exit_Function
    Else
        ' Check buffer was written
        If iWritten <> iSize Mod BUFFER_SIZE Then
            MsgBox "Upload - Failed!"
            ShowError
            FTPFile = False
            GoTo Exit_Function
        End If
    End If
               
Exit_Function:

' remove progress meter
Retval = SysCmd(acSysCmdRemoveMeter)

'close remote file
Call InternetCloseHandle(hFile)

'close local file
Close iFile

' Close Internet Connection
Call InternetCloseHandle(hOpen)
Call InternetCloseHandle(hConnection)

Exit Function

Err_Function:
MsgBox "Error in FTPFile : " & Err.Description
GoTo Exit_Function

End Function
Avatar of Jim Dettman (EE MVE)
Jim Dettman (EE MVE)
Flag of United States of America image

Many FTP clients/servers won't let you do that (rename).  Instead give it the name you want it to end up with right away by making RemoteFileName different then LocalFileName

Jim.
Sorry, just re-read what you wrote and I missed the point a bit; it's sDir that you want to make sure that is correct as it is what is being used to set the FTP directory:

' Change Directory
Call FtpSetCurrentDirectory(hConnection, sDir)

Between that and RemoteFileName, you'lll be able to put a file right where you want it and there should be no reason that you need to re-name it.

Jim.
Avatar of Mik Mak
Mik Mak

ASKER

Hi Jim

It's not because I don't know where to put the file - it's part of the customers solution that it should be done this way - first copied, then renamed - it's because of the way their system picks up the orders from the ftp server - so I need that functionality although it's a bit silly :) Can you help me ?
Avatar of Mik Mak

ASKER

I guess FtpRenameFile could work
ASKER CERTIFIED SOLUTION
Avatar of Jim Dettman (EE MVE)
Jim Dettman (EE MVE)
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Mik Mak

ASKER

Yes I tried that, but can't make it work

I've put in this in the function shown in the question header

 If sDirRen <> sDir And FTPFile Then
        Call FtpRenameFile(hConnection, sDir & RemoteFileName, sDirRen & RemoteFileName)    End If

And I've also put in this declaration, but it fails to do the rename

Public Declare Function FtpRenameFile Lib "wininet.dll" _
    Alias "FtpRenameFileA" (ByVal hFtpSession As Long, _
    ByVal lpszExisting As String, ByVal lpszNew As String) As Boolean
<< If sDirRen <> sDir And FTPFile Then
        Call FtpRenameFile(hConnection, sDir & RemoteFileName, sDirRen & RemoteFileName)    End If
>>

  The remarks on RenameFile read:

"The lpszExisting and lpszNew parameters can be either partially or fully qualified file names relative to the current directory. A backward slash (\) or forward slash (/) can be used as the directory separator for either name. FtpRenameFile translates the directory name separators to the appropriate character before they are used. "

 So it sounds like it might work like this:

If sDirRen <> sDir And FTPFile Then
        Call FtpRenameFile(hConnection, sDir & "\" & RemoteFileName, sDirRen & "\" & RemoteFileName)
End If


Give that a go.  Not sure it will work though.  Note that it says "Current directory".  It may only allow a file rename and not a directory move.

<< - it's part of the customers solution that it should be done this way - first copied, then renamed - it's because of the way their system picks up the orders from the ftp server - >>

  Only thing I can think of is that they are trying to avoid picking up a partial file (reading it as it is being uploaded).   Uploading it and then shifting it to another directory is basically an atomic operation, so by doing that they are ensuring that the upload is complet before they try to grab it.

Jim.
Avatar of Mik Mak

ASKER

Yes, thats exactly what theyre triyng to avoid - reading a partially uploaded file :)

My sDir and sDirRen alreay contains a "/" so that can't be the problem I guess :) Any other ideas ?
Try it this way:

If sDirRen <> sDir And FTPFile Then
        Call FtpRenameFile(hConnection, RemoteFileName, sDirRen & RemoteFileName)
End If

  Beyond that, no, no more ideas.  I typically don't use the wininet.dll, but even so, the only way I know to "move" a file on a FTP server from one directory to another is with the rename command, but not all clients/servers support that either.

Jim.
Avatar of Mik Mak

ASKER

I've now tried the command manually and directly on the ftp server and can't make it work there - so maybe it's not the code :) ?
<<I've now tried the command manually and directly on the ftp server and can't make it work there - so maybe it's not the code :) ?>>

 Sounds like a server issue then if you can'y rename it manually with a client.  I would ask them what server software they are running and version, then find out if it supports the rename command.

Jim.
Avatar of Mik Mak

ASKER

It was them who requested the rename procedure, so I've asked them why it fails when trying to do it manually.

Thank you for the advice