GeniuS BraiN GeniuS BraiN - 6 months ago 18
Vb.net Question

FtpWebRequest: create nested directories (local vs remote)

Objective:

I want to make sure that FTP path exists before uploading files, if not ==> create it.

Code I'm using:

Dim ftpPath As String = "ftp://----------/ParentDir/SubFolder1/SubFolder2"
If Not FTPDirExists(ftpPath) Then
CreateFTPDir(ftpPath)
End If


Where
CreateFTPDir
is:

Private Sub CreateFTPDir(DirPath As String)
Dim request As FtpWebRequest = FtpWebRequest.Create(DirPath)
request.Credentials = New NetworkCredential("UserName", "Password")
request.Method = WebRequestMethods.Ftp.MakeDirectory
request.Proxy = Nothing
request.KeepAlive = True
Try
Dim resp As FtpWebResponse = request.GetResponse()
Catch ex As Exception
Console.WriteLine(ex.Message)
End Try
End Sub


Now, when I test this code on my local FTP server (created using FileZilla), it creates the path no matter the number of nested directories.. but when I use it on the actual (remote) FTP server, it throws the following exception:
The remote server returned an error: (550) File unavailable
if the directories to create are more than one.

My question is why doesn't this problem occur with the local server? and do I have to create each nested directory separately on the remote server?




Additional info + 2nd question:

This is the
FTPDirExists
function I'm using (the best I could come up with after a lot of searching):

Private Function FTPDirExists(DirPath As String) As Boolean
DirPath &= If(DirPath.EndsWith("/"), "", "/")
Dim request As FtpWebRequest = FtpWebRequest.Create(DirPath)
request.Credentials = New NetworkCredential("UserName", "Password")
request.Method = WebRequestMethods.Ftp.ListDirectoryDetails
request.Proxy = Nothing
request.KeepAlive = True
Try
Using resp As FtpWebResponse = request.GetResponse()
Return True
End Using
Catch ex As WebException
Dim resp As FtpWebResponse = DirectCast(ex.Response, FtpWebResponse)
If resp.StatusCode = FtpStatusCode.ActionNotTakenFileUnavailable Then
Return False ' ==> Unfortunately will return false for other reasons (like no permission).
Else
Return False ' ==> Don't bother about this.
End If
End Try
End Function


It's not 100% accurate as I referred in the comment above, so please let me know if you have a more accurate method.

Answer

I've decided to use another function that creates each folder of the path separately:

Public Shared Sub CreatePath(RootPath As String, PathToCreate As String, Cred As NetworkCredential)
    Dim request As FtpWebRequest
    Dim subDirs As String() = PathToCreate.Split("/"c)
    Dim currentDir As String = If(RootPath.EndsWith("/"), RootPath.Substring(0, RootPath.Length - 1), RootPath)
    For Each subDir As String In subDirs
        currentDir &= "/" & subDir

        request = DirectCast(FtpWebRequest.Create(currentDir), FtpWebRequest)
        request.Credentials = Cred
        request.Method = WebRequestMethods.Ftp.MakeDirectory
        request.Proxy = Nothing
        Try
            Dim response As FtpWebResponse = DirectCast(request.GetResponse(), FtpWebResponse)
            response.Close()
        Catch ex As Exception

        End Try
    Next
End Sub