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(hCo nnection, 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(hConne ction)
Exit Function
Err_Function:
MsgBox "Error in FTPFile : " & Err.Description
GoTo Exit_Function
End Function
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,
' Change Directory
Call FtpSetCurrentDirectory(hCo
' 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
'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
' 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(hConne
Exit Function
Err_Function:
MsgBox "Error in FTPFile : " & Err.Description
GoTo Exit_Function
End Function
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(hCo nnection, 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.
' Change Directory
Call FtpSetCurrentDirectory(hCo
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.
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 ?
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 ?
ASKER
I guess FtpRenameFile could work
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
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
I've put in this in the function shown in the question header
If sDirRen <> sDir And FTPFile Then
Call FtpRenameFile(hConnection,
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.
Call FtpRenameFile(hConnection,
>>
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,
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.
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 ?
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.
If sDirRen <> sDir And FTPFile Then
Call FtpRenameFile(hConnection,
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.
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.
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.
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
Thank you for the advice
Jim.