Friday, February 15, 2008

Uploading, Downloading and More

I’ve always wanted some commands in the Visual FoxPro language that would make uploading and downloading files from websites, FTP sites, and file locations extremely easy. Oh, and I also wanted progress indication for these uploads and downloads to be easy to implement as well. Having mucked around with various class libraries and 3rd Party components for years, I decided it was time to write an FLL that did exactly what I wanted so I created vfpconnection.fll.

VFPConnection FLL

Internally vfpconnection.fll is using the LibCurl library (here's their license), so there are tons of other features I can, and will, add to this as it moves forward. For now it provides VFP developers with what I believe are some of the simplest and easiest file upload and download functions for Visual FoxPro (FTPGet, HTTPGet, FileGet, FTPPut, HTTPPut, FilePut, FTPToStr, and HTTPToStr). It also provides the ability to download files from FTP and HTTP in memory (similar to VFP’s FileToStr function) which avoids disk IO all together and can prove quite convenient when a developer just wants to read something off of a server. And, it provides an extremely slick way of implementing progress indication via a callback function or method.

Next Up ...

I created a pretty cool example of how useful having an FLL like this can be. In my next blog entry I’ll present a VFP application I created called AppUpdate which you’ll be able to us as a pretty advanced (though still simple) Loader/Updater for your Visual FoxPro applications. Special thanks ahead of time go out to a client of mine that is allowing me to share it with my readers. In any event, until next time… Visual FoxPro Rocks!

Here's the customary download link, some sample code for using the vfpconnection.fll, and the library documentation...

VFP Connection FLL:

VFPConnection FLL Download (90 KB approx.)


VFP Connection Sample Code:

SET LIBRARY TO (LOCFILE("vfpconnection.fll","FLL"))

?FTPGet("FTP://myusername:mypassword@mysite.com/mydir/myfile.zip", "C:\myfile.zip", "MyCommand()")

?HTTPGet("http://www.mysite.com/mypage.htm", "C:\mypage.htm", "MyCommand()")

?FILEGet("File://C:\MyFile.txt", "C:\MyFileCopy.txt", "MyCommand()")

?FTPPut("C:\myfile.zip", "FTP://myusername:mypassword@mysite.com/mydir/myfile.zip", "MyCommand()")

?HTTPPut("C:\mypage.htm", "http://www.mysite.com/mypage.htm", "MyCommand()")

?FilePut("C:\myfile.zip", "File://C:\myfile.zip", "MyCommand()")

m.lcString1 = FTPToStr("FTP://myusername:mypassword@mysite.com/mydir/myfile.txt", "MyCommand()")

m.lcString2 = HTTPToStr("http://www.mysite.com/mypage.htm", "MyCommand()")

SET LIBRARY TO

FUNCTION MyCommand()
    ?nConnectTotalBytes
    ?nConnectBytesSoFar
ENDFUNC

 

VFP Connection Documenation:

Function FTPGet()

Signature: FTPGet(cSourceURL, cDestination[, cCallbackFunction)

Parameters:

cSourceURL - The URL to the file you wish to download.

cDestination - The full path and file name where you want the source file saved.

cCallbackFunction - An optional string denoting a function, procedure, or method that you want fired whenever a read/write occurs, such as "MyCallback()".

Return Value:

Logical - returns .T. if successful or .F. if the operation has failed.

Remarks:

This function provides the ability to download a file from an FTP site.

In order to specify port or login information you would simply include them in cSourceURL, such as “FTP://myusername:mypassword@myftpsite.com:21/mydir/myfile.zip”.

When the cCallbackFunction is called 2 variables (nConnectTotalBytes and nConnectBytesSoFar) are created dynamically by the FLL. These variables can be used within the specified function, procedure, or method to determine the total size of the source file in bytes as well as the total progress of the operation (Percentage = 100 * nConnectBytesSoFar / nConnectTotalBytes).


Function HTTPGet()

Signature: HTTPGet(cSourceURL, cDestination[, cCallbackFunction)

Parameters:

cSourceURL - The URL to the file you wish to download.

cDestination - The full path and file name where you want the source file saved.

cCallbackFunction - An optional string denoting a function, procedure, or method that you want fired whenever a read/write occurs, such as "MyCallback()".

Return Value:

Logical - returns .T. if successful or .F. if the operation has failed.

Remarks:

This function provides the ability to download a file from a website.

When the cCallbackFunction is called 2 variables (nConnectTotalBytes and nConnectBytesSoFar) are created dynamically by the FLL. These variables can be used within the specified function, procedure, or method to determine the total size of the source file in bytes as well as the total progress of the operation (Percentage = 100 * nConnectBytesSoFar / nConnectTotalBytes).


Function FILEGet()

Signature: FILEGet(cSourceURL, cDestination[, cCallbackFunction])

Parameters:

cSourceURL - The full path and file name to the file you wish to copy.

cDestination - The full path and file name where you want the source file saved.

cCallbackFunction – An optional string denoting a function, procedure, or method that you want fired whenever a read/write occurs, such as "MyCallback()".

Return Value:

Logical - returns .T. if successful or .F. if the operation has failed.

Remarks:

This function provides the ability to copy a file from a local or remote location.

The format for the cSourceURL parameter is slightly different than you might expect. In order to copy file C:\MyDir\MyFile.zip you would specify cSourceURL as  “FILE:// C:\MyDir\MyFile.zip”.

When the cCallbackFunction is called 2 variables (nConnectTotalBytes and nConnectBytesSoFar) are created dynamically by the FLL. These variables can be used within the specified function, procedure, or method to determine the total size of the source file in bytes as well as the total progress of the operation (Percentage = 100 * nConnectBytesSoFar / nConnectTotalBytes).


Function FTPPut()

Signature: FTPGet(cSource, cDestinationURL[, cCallbackFunction)

Parameters:

cSource - The full path and file name of the file you want uploaded.

cDestinationURL - The URL to where the file specified in cSource should be uploaded to.

cCallbackFunction - An optional string denoting a function, procedure, or method that you want fired whenever a read/write occurs, such as "MyCallback()".

Return Value:

Logical - returns .T. if successful or .F. if the operation has failed.

Remarks:

This function provides the ability to upload a file to an FTP site.

In order to specify port or login information you would simply include them in cDestinationURL, such as “FTP://myusername:mypassword@myftpsite.com:21/mydir/myfile.zip”.

When the cCallbackFunction is called 2 variables (nConnectTotalBytes and nConnectBytesSoFar) are created dynamically by the FLL. These variables can be used within the specified function, procedure, or method to determine the total size of the source file in bytes as well as the total progress of the operation (Percentage = 100 * nConnectBytesSoFar / nConnectTotalBytes).


Function HTTPPut()

Signature: HTTPGet(cSource, cDestinationURL[, cCallbackFunction)

Parameters:

cSource - The full path and file name of the file you want uploaded.

cDestinationURL - The URL to where the file specified in cSource should be uploaded to.

cCallbackFunction - An optional string denoting a function, procedure, or method that you want fired whenever a read/write occurs, such as "MyCallback()".

Return Value:

Logical - returns .T. if successful or .F. if the operation has failed.

Remarks:

This function provides the ability to upload a file to a website.

When the cCallbackFunction is called 2 variables (nConnectTotalBytes and nConnectBytesSoFar) are created dynamically by the FLL. These variables can be used within the specified function, procedure, or method to determine the total size of the source file in bytes as well as the total progress of the operation (Percentage = 100 * nConnectBytesSoFar / nConnectTotalBytes).


Function FILEPut()

Signature: FILEPut(cSource, cDestinationURL[, cCallbackFunction])

Parameters:

cSource - The full path and file name of the file you want copied.

cDestinationURL - The full path and file name where the file specified in cSource should be copied to.

cCallbackFunction - An optional string denoting a function, procedure, or method that you want fired whenever a read/write occurs, such as "MyCallback()".

Return Value:

Logical - returns .T. if successful or .F. if the operation has failed.

Remarks:

This function provides the ability to copy a file to a local or remote location.

The format for the cDestinationURL parameter is slightly different than you might expect. In order to copy file C:\MyDir\MyFile.zip you would specify cDestinationURL as  “FILE:// C:\MyDir\MyFile.zip”.

When the cCallbackFunction is called 2 variables (nConnectTotalBytes and nConnectBytesSoFar) are created dynamically by the FLL. These variables can be used within the specified function, procedure, or method to determine the total size of the source file in bytes as well as the total progress of the operation (Percentage = 100 * nConnectBytesSoFar / nConnectTotalBytes).


Function FTPToStr()

Signature: FTPToStr(cSourceURL[, cCallbackFunction)

Parameters:

cSourceURL - The URL to the file you wish to return a string from.

cCallbackFunction - An optional string denoting a function, procedure, or method that you want fired whenever a read/write occurs, such as "MyCallback()".

Return Value:

Character Data - the contents of the file specified by cSourceURL

Remarks:

This function provides the ability to retrieve a file from an FTP site as a string.

In order to specify port or login information you would simply include them in cSourceURL, such as “FTP://myusername:mypassword@myftpsite.com:21/mydir/myfile.txt”.

When the cCallbackFunction is called 2 variables (nConnectTotalBytes and nConnectBytesSoFar) are created dynamically by the FLL. These variables can be used within the specified function, procedure, or method to determine the total size of the source file in bytes as well as the total progress of the operation (Percentage = 100 * nConnectBytesSoFar / nConnectTotalBytes).


Function HTTPToStr()

Signature: HTTPToStr(cSourceURL[, cCallbackFunction)

Parameters:

cSourceURL - The URL to the file you wish to download.

cCallbackFunction - An optional string denoting a function, procedure, or method that you want fired whenever a read/write occurs, such as "MyCallback()".

Return Value:

Logical - returns .T. if successful or .F. if the operation has failed.

Remarks:

This function provides the ability to retrieve a file from a website as a string.

When the cCallbackFunction is called 2 variables (nConnectTotalBytes and nConnectBytesSoFar) are created dynamically by the FLL. These variables can be used within the specified function, procedure, or method to determine the total size of the source file in bytes as well as the total progress of the operation (Percentage = 100 * nConnectBytesSoFar / nConnectTotalBytes).


Friday, February 15, 2008 9:59:47 AM (Central Standard Time, UTC-06:00)  #    Comments [16]
Friday, February 15, 2008 11:14:56 AM (Central Standard Time, UTC-06:00)
Craig,

COOL stuff... I am convinced you don't sleep!! I am looking forward to the next installment on this blog.
Friday, February 15, 2008 5:57:21 PM (Central Standard Time, UTC-06:00)
Wow - Fantastic!

Are you planning to add FTPS? Most of the third party ActiveX developers stopped adding features (like FTPS) and are developing only for .NET :(
Vasim
Friday, February 15, 2008 8:46:50 PM (Central Standard Time, UTC-06:00)
Is there a way to stop an FTP download in progress?
Peter
Friday, February 15, 2008 9:31:03 PM (Central Standard Time, UTC-06:00)
typo:
(Percentage = 100 * nConnectBytesSoFar / nConnectionTotalBytes)
Should be:
(Percentage = 100 * nConnectBytesSoFar / nConnectTotalBytes)
Peter
Friday, February 15, 2008 11:36:04 PM (Central Standard Time, UTC-06:00)
Vasim,

Yes, I plan to implement a number of other protocols and features in this FLL. In addition I need to add some additional error information so that when a call to one of the FLL's functions fails the developer will know why the exception occurred. This is just a first pass at this, more to come...


Peter,

Thank you for the correction. Cancelling a download or upload is not currently part of this FLL, but I will definitely add this feature to it.
Saturday, February 16, 2008 11:12:09 AM (Central Standard Time, UTC-06:00)
Craig,

You are publishing some of the most useful VFP utilities! I especially appreciate the well designed APIs, clear and intuitive.

Looking forward to VFPStudio. How is that project going?

Thank you very much.

Alex
Alex Sosa
Saturday, February 16, 2008 12:54:59 PM (Central Standard Time, UTC-06:00)
Oh boy, Craig, you are our hero.

Once again, a great addition to my worktools. Thanks again for your wonderful work and continuing contribution to our fox experience.

Michael
Saturday, February 16, 2008 1:10:29 PM (Central Standard Time, UTC-06:00)
Alex,

Thank you. I will be posting some stuff regarding VFP Studio in the next day or so here on my blog. I'm thinking of including a screen cast, so you can judge for yourself.

Michael,

Your are very welcome. Thanks for stopping by my blog and taking the time to post.
Thursday, February 21, 2008 7:05:41 PM (Central Standard Time, UTC-06:00)
Fabulous stuff Craig (as always)....

any chance you could add an FTPrename command? One particular app that uses FTP was about to get rewritten to use this FLL when i remembered i have to FTP as a .tmp file and then rename to prevent a 3rd party app on the server picking up the file prematurely.

Nigel
Saturday, February 23, 2008 3:23:04 PM (Central Standard Time, UTC-06:00)
Nigel,

Sure. If I get some time this weekend I'll implement this functionality and some of the other suggestions I've received. As soon as I have a working version I'll post it here on my blog.
Thursday, March 06, 2008 12:26:10 PM (Central Standard Time, UTC-06:00)
I have these definition in my inicio.prg

Set Library To (Locfile("VFPConnection.fll","FLL","Select")) ADDITIVE

But when i compile mi project i havce these error:

Unknown FTPGET - Undefined

Wath is the problem?
Thursday, March 06, 2008 5:25:50 PM (Central Standard Time, UTC-06:00)
The problem is that the compiler is ignorant of the functions contained within the FLL. However, FLL functions are given precedence over functions defined in VFP. So, what you can do to avoid this compiler error is add empty dummy functions to your main.prg (or wherever), such as putting the following in your code...

*!* Dummy Functions to avoid compiler errors
Function FTPGet()
Function HTTPGet()
Function FileGet()
Friday, March 07, 2008 10:24:10 AM (Central Standard Time, UTC-06:00)
Thanks Craig it´s Ok.
Wednesday, March 12, 2008 1:57:06 PM (Central Daylight Time, UTC-05:00)
Hi !

Is there any way to download all the files or list of files (File Skeleton) from the FTP Server ?

Is this tool support Win98 ?

Thanks
Ravi Mehrotra
Ravi Mehrotra
Thursday, April 24, 2008 5:36:13 PM (Central Daylight Time, UTC-05:00)
Hi.... very usefull tool... the question is...

I need to redistribute cURL with my programs ?

Very thanks
Juan P.
Thursday, July 24, 2008 11:55:52 AM (Central Daylight Time, UTC-05:00)
Hi Craig!
Firstly, cool tool. Saved my day!
There is a way to know the transfer rate (for example 1Kb/s) when downloading a file?

Thanks!
Name
E-mail
(will show your gravatar icon)
Home page

Comment (Some html is allowed: a@href@title, b, blockquote@cite, em, i, strike, strong, sub, super, u)  

Enter the code shown (prevents robots):


 

Archive

<July 2008>
SunMonTueWedThuFriSat
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789