# VBForums CodeBank > CodeBank - Visual Basic 6 and earlier >  To all who's doing FTP: Here's an FTP class to simplify things drastically

## jian2587

ok this is the reinvented version I promised long time ago.
there's a vbs script file that shows how to use the class file.
see, no events needed. well, you can use the events too, by using the 
wscript.connectobject method.



VB Code:
'To use this class, declare it like this
Dim WithEvents ftpConn As ftpConnection
 'Create a new instance of it
Set ftpConn = New ftpConnection
 'To connect
ftpConn.User = "Anonymous"
ftpConn.Password = "Guest"
ftpConn.Passive = True ' Use passive mode
ftpConn.RemoteHost = "ftp.ftpsite.com"
ftpConn.RemotePort = 21 'default is 21
ftpConn.Connect

LISTING FILES + INFO

VB Code:
'lstFiles is a listbox
    If ftpConn.CommandState = CMD_LOGGED_IN Then
        'if you want just a list of names, use ftpConn.GetFileList()
        If ftpConn.GetFileListInfo() = True Then
            Do Until ftpConn.ListParser.IsParsed
                DoEvents
            Loop
            Dim i As Long
            lstFiles.Clear
            For i = 0 To ftpConn.ListParser.FileCount - 1
                lstFiles.AddItem ftpConn.ListParser.fileList(i, ftpConn.ListParser.ColumnCount - 1)
            Next
        Else
            MsgBox "FAILED"
        End If
    Else
        MsgBox "NOT LOGGED IN"
    End If

OK, so here's the thing. My ftp class no longer reads from/writes to files. You've to supply the data when it's needed (through the appropriate raised events).

DOWNLOAD

VB Code:
'You must declare a dataConnection object
Dim dataConn As dataConnection
 'Now you need to allocate a data socket
Set dataConn = ftpConn.NewDataConnection(ftpConn.IsPassive)
dataConn.DataType = TYPE_BINARY ' works for all types of files
 'To download
If dataConn.Initiate(True) Then 'true to asynchronously connect
    dataConn.StartTransfer TRANSFER_DOWNLOAD, "download.txt"
End If
 'Incoming data event
Private Sub dataConn_IncomingData(bytes As Long)
    Dim s As String
    s = dataConn.GetData() 'so now s holds (part of) the data
End Sub
 'If you're writing s to a file and don't know when to stop, use this event
Private Sub dataConn_StateChanged()
    If dataConn.DataState = DATA_DISCONNECTED Then
        dataConn.Dispose
        Set dataConn = Nothing
        'And close your file here
    End If
End Sub

UPLOAD

VB Code:
'You must declare a dataConnection object
Dim dataConn As dataConnection
 'Now you need to allocate a data socket
Set dataConn = ftpConn.NewDataConnection(ftpConn.IsPassive)
dataConn.DataType = TYPE_BINARY ' works for all types of files
 'To upload
If dataConn.Initiate(True) Then 'true to asynchronously connect
    dataConn.StartTransfer TRANSFER_UPLOAD, "download.txt"
End If
 'Upload data in this event, it'll be called every time the previous data
'chunk is fully uploaded
Private Sub dataConn_NeedData()
    If dataConn.DataState = DATA_TRANSFERRING Then
        dataConn.SendData "Hello, World!" ' replace this data with sth else
    End If
End Sub
 'When you're done uploading, you can close the connection here
Private Sub dataConn_SendComplete()
    'If all data is uploaded then
        'dataConn.Disconnect 'disconnect if you're done
    'End If
End Sub

CLEANING UP

VB Code:
'so you want to quit, do this.
ftpConn.Quit 'Kiss FTP Server Bye bye
ftpConn.Dispose 'Disconnect the sockets, destroy used objects
dataConn.Dispose
Set dataConn = Nothing
Set ftpConn = Nothing

To do other stuffs, like renaming/deleting/creating file/directory, etc, check out the class file. If there's some methods not provided, you can always use the SendCommand to send your own commands. Consult a FTP document.

The attached file has demo codes, so you can see how things work. And finally, please do credit me whenever you use part or all of my codes.

Thank you.

----------


## veryjonny

> _Originally posted by jian2587_ 
> Okay, shouldn't this be in the CodeBank or wut?
> Well, I dont think anyone would go there often, once they've a
> problem, they go here. To look for codes, they goto PSC instead.


you shd tell this to the  moderators :Big Grin: 


Thanks for the post.(havent tested it though) :Smilie:

----------


## Madboy

your wrong, its suprising how many people do visit the codebank. The other day i posted about 6 examples, and with an hour i had over 15 views for each thread.

----------


## veryjonny

> _Originally posted by Madboy_ 
> *your wrong, its suprising how many people do visit the codebank. The other day i posted about 6 examples, and with an hour i had over 15 views for each thread.*



then, Report it to the mods. 

they would move it anyways. :Big Grin:

----------


## jian2587

K, so it ain't a big mistake, huh?

These days I see some ppl having probs with FTP in this forum.
That's why I put it here.

----------


## BrianS

If they did a Search for FTP, then they would find it in the code bank.

----------


## Madboy

although the large amount of people who dont bother to use the Search facility would not be aware of it.

Lets see what the mods say eh

----------


## BrianS

Either way, if they dont do a Search, it will get buried here faster than if it was put in the Code Bank.  It will be off the first page by tonight.

----------


## Whatupdoc

is it possible to use this with a progress bar? cause it'll be useless to upload a big file without knowing when it will be done. anyone know a winsock version out there with a progress bar?

----------


## RudyL

> _Originally posted by Whatupdoc_ 
> *is it possible to use this with a progress bar? cause it'll be useless to upload a big file without knowing when it will be done. anyone know a winsock version out there with a progress bar?*


I was wondering the same thing... I would need a way to detect the progress...

----------


## randem

Search the forum, I helped someone make one. So I know it's out there. Search for FTP Randem, youre sure to find it.

----------


## <ABX

if you know the size of the upload/download set the pb.max to the files size and set pb.value to how much send/received

assuming pb is a progressbar

----------


## jian2587

Well, my class doesn't provide that.
But u can do it urself.
For example:
VB Code:
'Download file
objFTPC.OpenDataConnection
Do Until objFTPC.DataState = DS_INITIATED 'Sorry it's 
'DS_INITIATED, not DS_CONNECTED as previously mentioned
    DoEvents
Loop
objFTPC.DownloadFile "readme.txt"
'When transfer is starting, the event IncomingData will fire.
Private Sub objFTPC_IncomingData(bytesTotal As Long)
Dim sData As String
objFTPC.GetData sData, bytesTotal
'Write it on local file
Put #1, , sData
'And u constantly record the data length and from there u can
'calculate your progress

VB Code:
'To get the remote file's size
objFTPC.OpenDataConnection
Do Until objFTPC.DataState = DS_INITIATED
    DoEvents
Loop
objFTPC.ListFileInfo ""
'When the data is replied, u can check it via 
'objFTPC.FileInfo(Index).FileSize property

Later I shall post an example showing almost all u can do with
this class.

----------


## jian2587

Here's the codebank thread link:
http://www.vbforums.com/showthread.p...hreadid=278027

----------


## Hack

Moved To The CodeBank

----------


## jian2587

i have to admit, the class is full of bugs...and i did not follow the protocols correctly and fully.
if possible, i want to do a rewrite.
if you see me reply in a few days, that means i'm on it. if not, i may be too busy.
totally sorry for those random quirks.

----------


## RightPilot

What is codebank?

----------


## jian2587

CodeBank is the forum you are in right now; think of it as a place to store and share codes.

I rewrote the whole thing from scratch, with better and more streamlined codes. This also means there's no spaghetti codes and it'll be easier for you to understand the codes. (I spent hours on this non-stop, and skipped my lunch  :Frown: , so I hope you'll for the least credit me when you use my codes).

I also try to follow the ftp protocol as much as is possible, but I don't provide much out-of-the-ordinary case handling. The class has methods where you can use to check out such cases, and you can take care of them yourself.

The class now doesn't write the incoming data to the file for you, nor does it read the file when you're uploading. Events will be raised whenever there's new data (download) or data is needed (for upload). You can use GetData and SendData method of the class to do this. This is in line of OOP's guideline.  The class shouldnt do too much things on its own.

Now what's left undone is directory listing parsing. I can parse only UNIX and WINDOWS NT format (the two most widely used format). If you happen to use other formats, you have to write your own parser. I'm thinking of separating the parser as another class instead of integrating it into the ftp class. So we can implements different kinds of parser. To know which parser to use, SYST usually gives you a good idea what kind of system the ftp server is on.

I guess I can get it done tonight, and then I also need to test and debug. When the codes are ready I'll upload it asap.

----------


## jian2587

By the way, if you want to do progress kinda things, you can first get the file size by getting the file list info (then the parser will parse for you), and depending on what system the ftp server is on, the file size may be on different columns. Use the appropriate column index in calling listParser.FileList to get the size. On UNIX, it's on 5th column (column index 4). On Windows NT with MS-DOS style output, it's on 3rd column (column index 2).

So you've the complete file size, now you can update the progress in the IncomingData event.

----------


## jian2587

Note: when up/downloading, the class file doesn't open/read/write the local file for you.
When uploading, the NeedData event and SendComplete event will fire alternately, and repeatedly. You upload the data by using dataConn.SendData in the NeedData event. Send in chunks, not whole thing at once. When you're done, you can use dataConn.disconnect in the SendComplete event.
Same thing with downloading. The IncomingData event will fire repeatedly until all data has been acquired. It'll close automatically when it's done.

----------


## mathy2007

many thanks to the guy who wrote this,

I am having problems trying to get the list of files to appear in the lstfiles textbox. When the program is running the get file list is clicked, the list box does not show any directory listings! Even changing the CWD, it does not work.

please help

----------


## jian2587

Did you try logging in first? Was it successful?
If it was, was the directory you were accessing protected? i.e. the server does not allow you to list its contents?
If it wasn't, did you wait long enough? I'm aware that IIS ftp server on localhost is somewhat retarded when it comes to returning file list.
I've not touched the code for a long time, however, I did remember there's a parser class that helps parse file list data. Windows NT server, Unix server, and any other kinds of servers on different platforms return the file list differently. The parser I have written is able to parse the two dominant ones only, namely NT and Unix. You may want to check what the server is by sending a SYST command.
Also, check firewall settings?
And try FTP passive mode if possible.

----------


## mathy2007

Thanks for responding

First of all, the conection works to the FTP server and its a UNIX server.  I wouldnt imagine the directories are protected as others programs can retrieve the listings and i did leave it long enough.  The server is not on my computer, its actually my XBOX. The firewall is open to the connections and i did try passive mode which is just giving the same reults.  I also tried using the different columbs but no results.

Thanks
Mathy

----------


## jian2587

post some snap shots. that'll help me diagnose the problem.

----------


## mathy2007

thanks mate, your help is really appreciated.

I have taking a couple o snap shots to help


Log on screen


Get File List - This is the problem
As you can see there has been 5 entries added all with no names,
This is the root drive and there is five folders


SYST command to show file server


To show by changing directory, it still doesnt show the contents
Does not show file or folder names.

Thanks
Mathy

----------


## jian2587

i see. i'm away from my source codes now. as far as i can remember, the ftp class invokes a parser class to parse the data. i can't duplicate your situation, but i'll peek around at the parser class, and here's what i recommend while you wait. study the parser class's methods a bit and you can use a debug.print or anything to display the raw data. if you see the file list data, then it can only mean the parser didn't parse things right. if you don't see anything, you can check the data socket's incomingdata event in the ftp class file. you can dump them on the screen as the data pours in. if you see the file list data, then that means the data handling has got problems.

network->data socket->ftp class->parser class->list box

you probably wanna check at what point (which arrow) the data disappears.

i still believe it's the parser's fault though.

----------


## FD 80

There is a small bug in getting the File list. The flag "ftpConn.ListParser.IsParsed" is never cleared once it is set.

I had to make these modifications (there is perhaps a better way):


```
'Added this to ftpListParser
Public Sub ClearIsParsed()
    bParsed = False
End Sub
```

and here:



```
'Added clear flag calls to ftpConnection
Public Function GetFileList(Optional ByVal directory As String = "") As Boolean
    ChangeDataType TYPE_ASCII
    Me.ListParser.ClearIsParsed
    listConn = NewDataConnection(userPasv)
    If listConn.Initiate(True) = True Then
        Call listConn.StartTransfer(TRANSFER_NLST, directory)
        GetFileList = True 'oops, don't forget this
    Else
        GetFileList = False
    End If
End Function

Public Function GetFileListInfo(Optional ByVal directory As String = "") As Boolean
    GetFileListInfo = False
    ChangeDataType TYPE_ASCII
    Me.ListParser.ClearIsParsed
    Set listConn = NewDataConnection(userPasv)
    If listConn.Initiate(True) = True Then
        Call listConn.StartTransfer(TRANSFER_LIST, directory)
        GetFileListInfo = True
    Else
        GetFileListInfo = False
    End If
End Function
```

Wicked Great bit of code BTW !  :Smilie:  
Many thanks.

----------


## jian2587

Oh I don't think that's a bug. It's intended to be never cleared. Because every time a file list is obtained, a new list parser class is created...or did I not? in that case, it's good you changed it  :Smilie:

----------


## FD 80

Hmmm, I must of hit an instance where it wasn't re-creating the class. (Of course it is entirely possible that I just did something improper.)
 Basically I was playing around with it and added a change directory button.



```
Private Sub cmdCWD_Click()
    If Not ftpConn.ChangeDirectory(lstFiles.Text) Then
        MsgBox "Failed"
    End If
End Sub
```

I basically connected, retrieved a file list that included directories, selected a directory and changed the working directory, but when I hit Get File List again, it just displayed the last file listing. I had to hit it again to get the new list. I found by adding the modifications that the problem went away.

----------


## jian2587

when i think back, the only reason I write the ftp class this way (i.e. with control socket and data socket as two separate classes) is the idea that there can be MULTIPLE ftp transfers running simultaneously. I had mentioned I've never tried doing simultaneous multiple transfers.

Now it occurs to me the ftp protocol is designed to transfer one file at a time, per control socket connection. if that's the case, it adds unnecessary level of abstraction of complication to have the data transfer as a separate class.

I actually have a new version, with cleaner and better codes; also, without the separate data transfer class. Basically, an ftp client class and a list parser class is all we need.

In this newer version, programmer actually has the option of coding their ftp thing in two ways. Either use events, or do->check state->loop. The latter is for linear execution of codes, suitable for scripts...e.g. vbscripts.

The code to initiate a transfer is easier than ever (not as easy as ftp.getfile("blah.txt"), and is intended to not to be this easy and rigid), while still retaining the flexibility.

I'll upload the codes soon, after tidying up the example codes.

----------


## FD 80

I found a handy piece of file list parsing code by D. J. Bernstein http://cr.yp.to/ftpparse.html

I adapted some of it to VB and added it to the list parser. I excluded the date/time extraction as I was more interested in name, size, folder vs file. But I am sure anyone interested can follow the link and adapt that portion of it.

I only tested it with Unix style listing. Handles long file names alright. It now gives a collection of 3 columns ( 'd' or '-' for folder vs file, size in bytes, name).

I have attached it here, if anyone finds it useful. (It may be a little ugly thought.)

----------


## jian2587

this is awesome FD 80!

oops i did not upload the latest codes I promised. It's a complete rewrite actually. Will do it soon.

----------


## mathy2007

hi, i cant seem to get the connections to work, would like some help please.

so far i have managed to get the files included and coded:
Set ftpConn = New Client.
ftpConn.Connect
text1.text=ftpConn.IsDataSent

text1.text displays 'False' and no outgoing connections are made, i have enetered all the other details such as ftp address and port number.  Firewall was disabled and so on. No connections are sent out. Do i need to include winsock to get this to work and if so, whats the name for it?

Please help.

----------


## jian2587

hi mathy, I'm not sure if you have the latest version. If not, please download it from the first post.
In the zip file, there's a vbs script file with sample codes. check that one out. if you still have problems, post it here.

----------


## mathy2007

hi jian, that was a quick reply. I have downloaded the new files from the first script but didnt realise their was a script file. i was trying to look at the ftpClient.vbp for help. Many thanks will have a look a come back to ya if any problems

Mathy

----------


## mathy2007

Hi Jian, all is going good but do have a question! How can i change the length of the timeout code, say to shorten it to 10 seconds?

Mathy

----------


## nowens

Hi Jian, first of all, thank you for the hard work.

My question (apologies for bothering you, my googling was not up to par):

I am converting this to .Net, and have gotten pretty much everything worked out (I believe) with the exception of the ws2_32.dll library declarations, namely the *as any* keywords for some of the variables.  And I can't determine what variable types they should be to make the changes.  Any advice?

Thank you.

----------


## jian2587

that would be As Object.

----------


## Dug25

Hi there, I'm trying to integrate this FTP class into my own project, and I keep on getting the error "Expected = " when I try to use the OpenFTP variable.  I've done the obvious things like added the class to the project.  Here's my code, hopefully someone will be able to point out where I'm going wrong. 


vb Code:
Private Function FTPUpload()    Dim ftpConn As FTPClass    Set ftpConn = New FTPClass        With ftpConn        .OpenFTP("site", "username", "password")            End WithEnd Function

Thanks

Dug

----------


## Dug25

Actually forget about that, I seem to have it working now.  I'll let you know how I get on with the class

Cheers

Dug

----------


## lok1234

how about SFTP? In case I am implementing Putty's SFTP public and private key model? Can I use the same code as above? Thanks

----------


## zpa0

I am trying to initiate data socket with method *InitiateDataSocket* but it doesn't work. Control connection is dropped, no PORT command is send to FTP server. Is active mode data transfer not implemented yet?

----------


## Lookover.at

Hello.

First of all:
Thanks fpr your work.
But im sorry, i could not handle it.
It was tooo curious and complicated.

Then i found this:
http://www.mcmillan.org.nz/paradoxes/code/FTPClass.html
and its realy great, and from my point of view, its much better and easyer.

Thanks, and best wished from vienna.
Tom www.lookover.at

----------


## yogiyang

I can't get it to work with SFTP servers.

Any idea as to how to do this?

----------


## bye360

sorry  i am poor english
i  very like your code and worship you high technology

why PASV mode can work normally in port mode cannot return a list of files

----------


## bye360

hello jian2587
Is active mode data transfer not implemented yet?

----------

