Ever wanted to write an application which constantly monitors a folder and raises events when there is any activity in that folder? In the good old days using VB6 or older you had to use the windows APIs to do something like this which was not very simple and required lots of coding. In this article. I am attempting to use System.Net.FtpClient to download some text files from an FTP server. I am a bit confused as to how I need to handle the stream and then write it to a file. System.Net.FTPClient - How to properly stream file. Ask Question 0. That could work in C#, but in VB.NET it does not have the same behavior.
![]()
The fine folks at Microsoft have been kind enough to provide us with the nuts and bolts for FTP functions in the WinINet.DLL. This DLL, which ships with Internet Explorer and a few other things, takes care of the low-level tasks outlined in the FTP protocol. All we have to do is wrap up a few of the functions provided so they're easy to call from our ASP code.
This sounds like a great opportunity to put our Visual Basic (VB) skills to work. A Little Help From Our Friends As mentioned, Microsoft has been kind enough to provide us with all the FTP functions in the WinINet DLL.
The documentation for the WinINet API is located at. As with most of the API documentation, it's intended for C programmers. So, if you don't understand C or are easily bored with the way API documentation drones on, keep on a-readin'.
Step by Step Let's jump right into it and perform an FTP GET on the file DIRMAP.TXT at FTP.MICROSOFT.COM and storing the file in C: DIRMAP.TXT. Once again the basic steps are:.
Setup the environment with a call to InternetOpen. Connect to the host by calling the InternetConnect function. Call the FtpGetFile function to get the file. Close the handles created in Steps 1 and 2, using the InternetCloseHandle function. Here's a closer look at each step. Setup the environment by calling the InternetOpen function. Here's the VB-specific declaration for the function call: Private Declare Function InternetOpen Lib 'wininet.dll' Alias 'InternetOpenA' (ByVal sAgent As String, ByVal lAccessType As Long, ByVal sProxyName As StringByVal sProxyBypass As String, ByVal lFlags As Long) As Long The sAgent parameter is used to specify the application or entity calling the WinINet functions.
For our purposes, we can put 'MyFTP Control'. The lAccessType parameter specifies whether we connect directly to a host or whether we use a proxy server for the connection. If we pass the value 1, we'll connect directly to the host. If we pass the value 3, we'll connect via a proxy server. If we pass 0, we'll connect based on the registry values ProxyEnable, ProxyServer, and ProxyOverride located under HKEYCURRENTUSER Software Microsoft Windows CurrentVersion Internet Settings.
Rather than using the registry settings, we can use the sProxyName and sProxyBypass parameters to provide the proxy server (or servers) and the list of IP addresses or names that should not be routed to the proxy. The basic format for listing a proxy is 'protocol=protocol://proxyname:accessport'. For example, to specify port 21 on Proxy1 as the proxy server, use 'ftp=ftp://Proxy1:21' as the sProxyName. To bypass any host that starts with 'nov', the sProxyBypass string would be 'nov.' . Finally, lFlags is used to indicate various options affecting the behavior of the InternetOpen function. For our example, we'll pass 0.
So, to open an Internet session without using a proxy, our call would be like this: lngINet = InternetOpen('MyFTP Control', 1, vbNullString, vbNullString, 0) If the function call fails, lngINet will be 0. Otherwise, lngINet holds the value of the handle that we'll need to pass to the InternetConnect function in the next step.
Connect to the host by calling the InternetConnect function. Here's the VB-specific declaration for the function call: Private Declare Function InternetConnect Lib 'wininet.dll' Alias 'InternetConnectA' (ByVal hInternetSession As Long, ByVal sServerName As StringByVal nServerPort As Integer, ByVal sUsername As StringByVal sPassword As String, ByVal lService As LongByVal lFlags As Long, ByVal lContext As Long) As Long The first parameter, hInternetSession is the value of the handle returned by the InternetOpen call.
SServerName is the IP address or host name of the FTP server we're connecting to. NServerPort indicates which port to connect to. For our example, we'll use the value 0, which indicates the default port (21).
SUsername and sPassword are used to pass the user name and password, respectively. The lService parameter is used to indicate the type of service to access, i.e., HTTP, FTP, etc. We'll always pass the value of 1, indicating the FTP service. If we pass the value x8000000 in the lFlags parameter, the connection will use passive FTP semantics. Otherwise, as in our example, we can pass 0 to use non-passive semantics. Finally, lContext is used to identify the application context when using callbacks. Since we're not using callbacks for our example, we'll pass 0.
So here's the call to connect to the host FTP.MICROSOFT.COM using the anonymous userid: lngINetConn = InternetConnect(lngINet, 'ftp.microsoft.com', 0'anonymous', '[email protected]', 1, 0, 0) If the function call fails, lngINetConn will be 0. Otherwise, lngINetConn holds the value of the handle that we'll need to pass to the FtpGetFile function in the next step. Now that we're connected, we need to call the FtpGetFile function. This function takes care of all of the housekeeping and overhead that comes along with reading a file on an FTP server and storing it locally. Here's the VB-specific declaration for the function call: Private Declare Function FtpGetFile Lib 'wininet.dll' Alias 'FtpGetFileA' (ByVal hFtpSession As Long, ByVal lpszRemoteFile As StringByVal lpszNewFile As String, ByVal fFailIfExists As BooleanByVal dwFlagsAndAttributes As Long, ByVal dwFlags As LongByVal dwContext As Long) As Boolean The first parameter, hFtpSession is the value of the handle returned by the InternetConnect call. LpszRemoteFile and lpszNewFile are the names of the file on the FTP server and the file to create on the local machine, respectively. The fFailIfExists flag is either 0 (replace local file) or -1 (fail if local file already exists).
DwFlagsAndAttributes can be used to specify file attributes for the local file. For our example, we'll overlook this and just pass 0. We use the dwFlags parameter to specify 1 for transferring the file in ASCII (Type A transfer method) or 2 for transferring the file in Binary (Type I transfer method). Since DIRMAP.TXT is an ASCII text file, we'll pass the value of 1. Finally, lContext is used to identify the application context when using callbacks. Since we're not using callbacks for our example, we'll pass 0.
So here's the call to get the DIRMAP.TXT file and store it in C: DIRMAP.TXT. In case the local file already exists, we'll overwrite it. BlnRC = FtpGetFile(lngINetConn, 'dirmap.txt', 'c: dirmap.txt', 0, 0, 1, 0) If the function call is successful, blnRC will be True, otherwise, blnRC will be False. At this point, the file has been received and now we're ready to close the connection and session handles using the InternetCloseHandle call. Here's the VB-specific declaration for the function call: Private Declare Function InternetCloseHandle Lib 'wininet.dll' (ByVal hInet As Long) As Integer.
As indicated, this function has only one parameter, hInet, that is the value of the handle to close or discard. Since, we have handles from the InternetConnection and InternetOpen functions, we'll need to call this close function twice. In addition, because the InternetConnection handle is dependent on the InternetOpen handle, we'll need to close these in the reverse order that we created them. So here are the calls: InternetCloseHandle lngINetConn InternetCloseHandle lngINet Congrats! In four short steps, we've done an FTP Get. Moving On What about the FTP functions like Put, Rename, Delete, etc?
Well, these functions are just as easy. Let's take a look at the Put function first. The basic steps are:. Set up the environment with a call to InternetOpen. Connect to the host by calling the InternetConnect function. Call the FtpPutFile function to get the file.
Close the handles created in Steps 1 and 2, using the InternetCloseHandle function. Looks real similar to our first step-through when we used the FtpGetFile function. In fact, the only difference, is in step 3 where we'll call FtpPutFile instead. Here's the VB-specific declaration for the function call: Private Declare Function FtpPutFile Lib 'wininet.dll' Alias 'FtpPutFileA' (ByVal hFtpSession As Long, ByVal lpszLocalFile As StringByVal lpszRemoteFile As String, ByVal dwFlags As LongByVal dwContext As Long) As Boolean The first parameter, hFtpSession is the value of the handle returned by the InternetConnect call.
LpszNewFile and lpszRemoteFile are the names of the file on the local machine and the file to create on the remote host, respectively. We use the dwFlags parameter to specify 1 for transferring the file in ASCII (Type A transfer method) or 2 for transferring the file in Binary (Type I transfer method). Since DIRMAP.TXT is an ASCII text file, we'll pass the value of 1. Finally, lContext is used to identify the application context when using callbacks. Since we're not using callbacks for our example, we'll pass 0. So here's the call to get the C: DIRMAP.TXT file and store it as DIRMAP.TXT on an FTP server: blnRC = FtpPutFile(lngINetConn, 'c: dirmap.txt', 'dirmap.txt', 1, 0) If the function call is successful, blnRC will be True, otherwise, blnRC will be False. As you can see, putting files on FTP servers is just as easy as getting files from FTP servers.
One word of caution, typically, the 'anonymous' user doesn't have access rights to create files on FTP servers. So, be sure that the user account used to connect to the FTP server has rights sufficient to create files. Otherwise, the FtpPutFile function call will return False, indicating the Put failed. Now let's delete a file named 'test.txt' by using the FtpDeleteFile function. Again, the function call in Step 3 is the only thing that changes.
Here's the VB-specific declaration for the function call: Private Declare Function FtpDeleteFile Lib 'wininet.dll' Alias 'FtpDeleteFileA' (ByVal hFtpSession As Long, ByVal lpszFileName As String) As Boolean The first parameter, hFtpSession is the value of the handle returned by the InternetConnect call. LpszFileName is the name of the file on the FTP server that we want to delete. So, here's the call to delete TEST.TXT on an FTP server: blnRC = FtpDeleteFile(lngINetConn, 'test.txt') If the function call is successful, blnRC will be True, otherwise, blnRC will be False. What's the Catch? Nearly all of the FTP functions are the same: set up the environment, connect to the host, perform the FTP task, clean up after ourselves.
As with most things, there are exceptions. What about getting a directory listing or reading the file contents without first getting the file? These types of FTP tasks are only marginally more complicated. Let's take a look at the directory listing problem. The basic steps for enumerating a directory are still the same.
We still have to set up the environment and connect to the FTP server before we do anything else. We also have to clean up the connection and environment handles once we're done.
To actually get the directory contents, we have to use two new functions: FtpFindFirstFile and InternetFindNextFile. The VB-specific declaration for FtpFindFirstFile is: Private Declare Function FtpFindFirstFile Lib 'wininet.dll' Alias 'FtpFindFirstFileA' (ByVal hFtpSession As Long, ByVal lpszSearchFile As StringlpFindFileData As WIN32FINDDATA, ByVal dwFlags As LongByVal dwContent As Long) As Long The first parameter, hFtpSession is the value of the handle returned by the InternetConnect call. LpszSearchFile is a directory path or file name on the FTP server.
If you specify an empty string, the current directory will be used. In addition, you can also specify wildcards. For example, to list the directory contents in the root directory that begin with ms, use ' ms.' . LpFindFileData is a little different from the other parameters we've used thus far. The datatype WIN32FINDDATA is a user-defined type that holds the received information about the files in the directory.
Here's what the type looks like: Private Type WIN32FINDDATA dwFileAttributes As Long ftCreationTime As FILETIME ftLastAccessTime As FILETIME ftLastWriteTime As FILETIME nFileSizeHigh As Long nFileSizeLow As Long dwReserved0 As Long dwReserved1 As Long cFileName As String. MAXPATH cAlternate As String.
14 End Type Notice that several of the variables have another user-defined datatype; FILETIME. Here's the type definition for them: Private Type FILETIME dwLowDateTime As Long dwHighDateTime As Long End Type For our example, we'll only use the contents of dwFileAttributes, which holds the file attributes, and cFileName, which holds the file name. Finally, dwFlags and dsContext aren't used for our example so we'll pass 0 for each. So here's the call to start a directory listing for the current directory: lngHINet = FtpFindFirstFile(lngINetConn, '.' , pData, 0, 0) If the function fails, 0 is returned.
Otherwise, lngHInet is a valid handle that we'll use to continue with the directory enumeration. In addition, the first file's name and attributes are stored in the pData variable. Once the FtpFindFirstFile function is called and returns a valid handle, we'll make calls to the InternetFindNextFile function until it returns an error of 18 indicating no more files to list. Here's the VB-specific declaration for InternetFindNextFile: Private Declare Function InternetFindNextFile Lib 'wininet.dll' Alias 'InternetFindNextFileA' (ByVal hFind As Long, lpvFindData As WIN32FINDDATA) As Long The first parameter, hFind is the value of the handle returned by the FtpFindFirstFile call.
LpvFindData is the same user-defined type that was used in the FtpFindFirstFile call and is used to store file information. So here's the call to get the next file in the directory: blnRC = InternetFindNextFile(lngHINet, pData) If the call was successful, blnRC returns True.
Otherwise, blnRC is false. To indicate that no more files exist, 18 is returned in the LastDllError of the Err object. So, referring back to our basic four-step process: Steps 1 and 2 (setting up the environment and connecting to a server) should have already been done.
The listing below would be Step 3. The final step, Step 4, would cleanup the environment and connection handles, just as before: Dim pData As WIN32FINDDATA Dim lngHINet As Long Dim intError As Integer Dim strTemp As String Dim blnRC As Boolean 'init the filename buffer pData.cFileName = String(260, 0) 'get the first file in the directory. LngHINet = FtpFindFirstFile(mlngINetConn, '.' , pData, 0, 0) 'how'd we do? If lngHINet = 0 Then 'get the error from the findfirst call intError = Err.LastDllError 'is the directory empty? If intError ERRORNOMOREFILES Then 'whoa.a real error.error handler. End If Else 'we got some dir info.
'get the name strTemp = Left(pData.cFileName, InStr(1, pData.cFileName, String(1, 0), vbBinaryCompare) - 1).store the file info someplace. 'now loop through the rest of the files. Do 'init the filename buffer pData.cFileName = String(260, 0) 'get the next item blnRC = InternetFindNextFile(lngHINet, pData) 'how'd we do? If Not blnRC Then 'get the error from the findnext call intError = Err.LastDllError 'no more items If intError 18 Then 'whoa.a real error.error handler.
Exit Do Else 'no more items. Exit Do End If Else 'get the last item returned strTemp = Left(pData.cFileName, InStr(1, pData.cFileName, String(1, 0), vbBinaryCompare) - 1).store the file info someplace. End If Loop 'close the handle for the dir listing InternetCloseHandle lngHINet End If So as you can see, even somewhat complicated tasks, such as enumerating directories, are easily framed in our simple four-step process: set up the environment, connect to the host, perform the FTP task, and close the environment and connection handles.
Your Very Own FTP ActiveX Server Component To complement this article, I've included the VB source code for an FTP ActiveX server component. The code consists of 3 class modules; clsITEM.CLS, colITEM.CLS, and FTP.CLS. ClsITEM.CLS contains the class definition, with clsITEM as the class name, for holding individual file information when enumerating a directory. ColITEM.CLS contains the class definition, with colItem as the class name, for collection of files using the clsITEM class. Finally, FTP.CLS contains the class definition, with ASPFTP as the class name, for all the FTP functions. I've also included the project file (FTPCLASSES.VBP).
Along with the source code, I've included sample ASP files for each of the functions and an include file (ASPFTP2.INC) that you can include in each of your ASP files to make some of the function calls easier. For example, here's the ASP code to use the FTP Get function. The server, userid, password, remote and local file names, type of transfer to use (i.e.
ASCII or Binary), and whether to replace the local file if it already exists are entered into a form (not shown) and referred to using the ASP Request object. Comments. I want change port Posted by brad on 09:56am Hello I wonder that if aspftp.dll has a property to set port number when I connect to server. Can I use other port number?. I need a 64-bit aspftp.dll for Windows Server 2012 R2 Posted by James on 03:55pm I need a 64-bit aspftp.dll for Windows Server 2012 R2. Is that available?.
Wrong type for bConnect produces an Error. Posted by Marcel on 12:27pm I'm using the Classes in Excel VBA. In the FTP Class there is a function 'Public Function bConnect As Variant'. It should be 'Public Function bConnect As Boolean'. In the 'As Variant' I get a type mismatch. The bGetFile method works fine.
Very Nice Posted by Christophe on 08:51am Thanks for this, very nice helpfull code. BR. Can not get file from ftp server to client Posted by botel on 04:32am Hello i'm use asp write code and use IIS is web server I want to get file from ftp server to client if i'm specify LocalFile = path of on ftp server is success but i'm use My Computer A is ftp server and MyComputer B is client When I'm i'm specify LocalFile = path of on My computer B It not succes thank you.
what is os version? Posted by botel on 06:17am what is os version? I'm use window7 64 bit then I'm test to run project but error 'Microsoft VBScript runtime error '800a01ad' ActiveX component can't create object /myASP/AspFTP2QGetform.asp, line 10' thank you.
I want buy aspftp.dll (FTP ActiveX Server Component) for win7 Posted by majiamin on 05:34am Do you have aspftp.dll (FTP ActiveX Server Component) for win7 system? How much money it needs? I want buy it. You must have javascript enabled in order to post comments.
Leave a Comment. Your email address will not be published. All fields are required. Name.
Email. Title. Comment.
Comments are closed.
|
AuthorWrite something about yourself. No need to be fancy, just an overview. ArchivesCategories |