Integral FTP is a JavaScript FTP client library or, more specifically, it is a JavaScript wrapper for an invisible Java FTP applet. It makes it possible to integrate FTP functionality directly into browser-side code.
Integral FTP differs from conventional FTP applets in that it does not have a Java-based user interface. Any user-interface used with Integral FTP (such as that at www.integralftp.com) is written in HTML. This means that the user-interface is 100% customizable by the web developer. In fact, many possible applications of Integral FTP would not even require the user to be aware that FTP is involved (e.g. SubmitFormToFTP).
Examples where Integral FTP would be useful are:
IntegralFTP.jar is a Signed Java Archive, which means that browsers pop up a message-box recommending that the user should permit the applet to run. It is signed using a certificate that will expire one year after it is issued. Once the certificate has expired the browser will no longer recommend that the user should permit the certificate to run, and may even block it without prompting the user. It is therefore necessary to renew the certificate each year.
EnterpriseDT will make a new signed Java archive available each year. Customers may download this archive free of charge. Alternatively, they may choose to sign the archive using their own certificate, which may have a longer expiration period. Please contact us for more information on how to do this.
Integral FTP necessarily uses an "asynchronous" programming model. This means that all FTP operations are launched in the background, allowing the browser to continue servicing the user-interface without having to wait for FTP operations to complete. The user is notified of the completion of an FTP operation by means of a "callback function".
Asynchronous programming is necessary because FTP operations, such as transferring large files, often take several minutes and if this methodology was not used then the browser would freeze for this length of time.
The best way to explain the Integral FTP programming model is by means of an example:
This example assumes that there's an HTML button whose onclick event calls the connectButtonClick() shown above. FTP operations are performed on an instance of the JavaScript class, FTPClient. In fact, this class needs to be initialized using its initialize() function, but this is left out in this example for the sake of simplicity.
The first step is to set the host-name, user-name and password of the FTP account. Next, the callback function for the connect operation is called. This is done by assigning the onConnect member of the FTPClient class. In this case ftp.onConnect is set to ftpConnected, which is the function defined immediately below the connectButtonClick() function.
Once the onConnect callback has been set we launch the connection operation by calling ftp.connect(). This instructs FTPClient to begin trying to connect to the server. This often takes several seconds and if the JavaScript engine had to wait for the connection to be made then the user would notice that their browser froze for that time. However, since the operation takes place in the background (within the Java applet), the JavaScript engine is free to go back to servicing the user-interface without delay and no freeze will occur.
Of course, we need to know when the connection attempt has completed and whether or not it has succeeded. We know this because our ftpConnected function will be called at that point. It is passed a single argument, status, which is of the type FTPCallbackStatus. One of the members of this class is a boolean variable called success and this indicates whether or not the connection attempt was successful.
In this instance we don't actually want to do anything other than checking the connection, so if the connection attempt was successful then we just go ahead and disconnect straight away by calling ftp.disconnect(). We don't really need to know when the disconnection operation completes so we don't worry about setting the corresponding callback, onDisconnect.
Notice that the FTP operation that logically followed the connection operation, i.e. disconnect, was placed inside the onConnect callback. This pattern of chaining sequential operations by launching them from within callbacks needs to be followed when programming with Integral FTP.
Perhaps the most distinctive aspect of programming with Integral FTP is its dependence on callbacks. While unusual in JavaScript due to its single-threaded nature, it is quite common in other languages such as Java, C# and C++.
The example above illustrated execution single FTP operation, and hinted at the way in which a sequence of operations should be implemented. The following table illustrates how a sequence of synchronous operations should be implemented asynchronously.
Synchronous Approach | Asynchronous Approach |
function doThreeOperations()
{
if (ftp.doOperationA() )
{
if (ftp.doOperationB() )
{
ftp.doOperationC() ;
}
}
}
|
function doThreeOperations()
{
ftp.onDoOperationA = onOperationADone;
ftp.onDoOperationB = onOperationBDone;
ftp.doOperationA() ;
}
function onOperationADone(status)
{
if (status.success)
{
ftp.doOperationB() ;
}
}
function onOperationBDone(status)
{
if (status.success)
{
ftp.doOperationC() ;
}
}
|
The column on the left shows the conventional (synchronous) way in which a sequence of three operations would be executed. The execution of the last two operations is each dependent upon the success of the previous operation.
The right column executes the same operations asynchronously. The first step is to assign the callback functions. Each asynchronous method has a corresponding callback, which is called when the method completes. Each of the callbacks is passed an argument, status, of type FTPCallbackStatus. This argument is tested to see if the operation succeeded. If it did then the next method is called. This is the way in which FTP operations are sequenced with Integral FTP.
Some callbacks have other arguments in addition to status. For example, the onSize callback is passed the name of the file that was downloaded as well as its size.
Every asynchronous method returns an integer called a "task ID". This number uniquely identifies the method call and is also available in the callback variable, FTPCallbackStatus.taskID. An important use of tasks identifiers is cancelling transfers. This is explained in the section on uploading and downloading files below.
One advantage of the asynchronous programming model used in Integral FTP is that it allows several operations to be executed concurrently. As described previously, callbacks are invoked when an operations are completed, however, when a callback is called it's not immediately obvious which invocation it relates to. The concept of "tags" deals with this issue. Every asynchronous method takes an optional tag argument, which can be of any type. This tag is made available in the corresponding callback through the FTPCallbackStatus.tag variable.
The following example displays a message-box containing "Hello World" once the operations is complete:
Integral FTP development centres around the FTPClient class. Usage generally follows the following pattern:
Firstly, the ftpclient.js file needs to be included into the HTML file using code like the following
A new instance of FTPClient should then be created and assigned to a variable:
It's important to note that an FTPClient cannot be used until it's been initialized.
FTPClients must be initialized before they can be used. Initialization is done by calling the initialize() method. Normally some action is required when initialization is complete (such as connecting to a server). In such cases the onInitialize callback should be set to point to a function that will be called when initialization is complete, as shown below:
The first argument to initialize() is the path (relative or absolute) to the IntegralFTP.jar file, the second argument determines whether or not the splash is displayed, the third is the logging level ("ALL", "DEBUG", "INFO", "ERROR", or "OFF"), and the fourth determines whether or not a log-file will be written in the machines TEMP directory.
In addition to making sure that the FTPClient has been initialized, the connection details (remote-host, user-name and password) must be set before a connection is made. Again, a callback is usually also required.
FTP connections are closed using the FTPClient.disconnect method.
Data connections may be set up in two different ways, active and passive. Note that active and passive refer to the operation of the FTP server, not the client.
Passive mode: In passive mode, the client sends a PASV command to the server. This tells the server to listen for a connection attempt from the client, hence the server is passively waiting. The server replies to PASV with the host and port address that the server is listening on. The client deciphers this reply and when a data connection is required, attempts to initiate the connection to the server at this address.
Passive mode may be selected as follows:
Active mode In active mode, the server actively connects to the client. To set up active mode, the client sends a PORT command to the server, specify the address and port number the client is listening on. When a data connection is required, the server initiates a connection to the client at this address.
Active mode may be selected as follows:
FTPClient supports the following FTP operations:
All of these are implemented using the asynchronous paradigm that was described above. Details of the methods are given in the Integral FTP API Reference.
Files may be uploaded using code like the following:
If progress updates are required then the onTransferProgress callback should be used.
The code required for downloading is almost identical.
Integral FTP allows transfers to be cancelled using the FTPClient.cancelTransfer() method. This method takes a single argument, taskID, which identifies the transfer that is to be cancelled. Once a cancellation has been achieved the onFileUploaded/onFileDownloaded is called with status.success=false.
Refer to the API reference for more details on FTPClient.uploadFile, FTPClient.downloadFile and FTPClient.cancelTransfer.
Text (i.e. strings) may be uploaded directly to a file on the server without use of local files.
Text downloads are also available, but the code is slightly different since the downloaded string is passed into the callback function:
Refer to the API reference for more details on FTPClient.uploadText and FTPClient.downloadText.
FTPClient has methods for listing files in both local and remote directories.
Remote directories may be listed as follows:
In addition to the usual status argument, a string containing the path of the directory, and a FTPFileList object are also passed to the callback. The FTPFileList has a member, files, which is an array of FTPFile objects, each of which denotes the name, size and date of a file.
The FTP server maintains a working directory for each session. This can be queried using the getWorkingDirectory() method, which is synchronous and therefore does not require callbacks. The working directory may be changed using the changeDirectory() method, which is asynchronous and returns its result to the onChangeDirectory callback method.
Refer to the API reference for more details on FTPClient.directoryList, FTPFileList, FTPFile, FTPClient.getWorkingDirectory and FTPClient.getWorkingDirectory.
Local directory listings may be obtained in a similar fashion - see FTPClient.localDirectoryList.
FTPClient has methods for deleting and renaming local and remote files (see FTPClient.localDeleteFile, FTPClient.localRename, FTPClient.deleteFile and FTPClient.renameFile).
The sizes and last-modified-times of local and remote files can be queries using the following methods: FTPClient.localSize, FTPClient.localModifiedTime, FTPClient.size and FTPClient.modifiedTime).
All of the methods mentioned above are asynchronous so callbacks need to be used, especially for the size and modified-time methods since that is the only way to access the results.
Integral FTP, like all EnterpriseDT products, has very extensive logging capabilities.
The logging level should be set when the
FTPClient.initialize method is called. By default,
logs are written to the Sun Java Console. This console may be enabled via the Java
Control Panel. Logs may also optionally written to a file called IntegralFTP.log,
which is located in the machines temporary directory (often C:\Windows\Temp).