Chinaunix首页 | 论坛 | 博客
  • 博客访问: 630641
  • 博文数量: 125
  • 博客积分: 8703
  • 博客等级: 中将
  • 技术积分: 1102
  • 用 户 组: 普通用户
  • 注册时间: 2010-03-10 17:48
文章分类

全部博文(125)

文章存档

2012年(2)

2011年(3)

2010年(11)

2009年(1)

2008年(12)

2007年(58)

2006年(38)

分类: Java

2008-04-07 15:20:47

Connecting to an FTP server with edtFTPj/Free is simply a matter of:

1.    Creating an object

FileTransferClient ftp = new FileTransferClient();

2.    Setting the remote host and user credentials

ftp.setRemoteHost(host);
ftp.setUserName(username);
ftp.setPassword(password);


3.    Calling the connect() method, which connects to the server and logs in.

ftp.connect();

4.    Logging out and closing the connection.

ftp.disconnect();


The connect() call will return when successfully connected and logged in, or throw an exception if it fails to connect or log in.

Note that the automatic login can be disabled using the advanced settings, which must be obtained via .

ftp.getAdvancedFTPSettings().setAutoLogin(false);

If autologin is disabled, must be be used to log into the server after connect() has been called (and prior to any remote operations being performed):

ftp.connect();
ftp.manualLogin();


get a directory listing

There are two basic ways to get a list of the files in a particular directory on an FTP server. The simpler way gets the names of the files using the method:

string[] files = ftp.directoryNameList();

This results in the files array containing the name of the files and directories in the current working directory on the server. 

FTP servers can return more information than just the names of the files and directories. This information can be returned as an array of strings by using an overloaded method. The 'full' boolean flag must be set to true to get the full listing:

string[] descriptions = ftp.directoryNameList("mydirname", true);

For convenience, the detailed file and directory information can be interpreted and returned as an object, in the method:

FTPFile[] files = ftp.directoryList();

This method returns an array of objects containing information about the files in the directory - details such as the size of the file and whether or not it is a directory. 

If a listing of a directory other than the current working directory is required it is recommended that the remote working directory be changed to that directory, as described in . The relative or absolute path may be passed to either method, but some FTP servers do not support this feature. In these cases changing directories should work.

Changing locale

Sometimes the directoryList() method will fail with a ParseException, citing a date string that it cannot interpret. This is often because the FTP server is in a different locale to the client. It may be returning month names that cannot be understood in the client's locale. For example, an FTP server in a German locale will return German month names, which cannot be interpreted by a client in a locale that uses English. To solve this, the server's locale should be set in the client, before connecting, via the method:

Locale[] locales = new Locale[2];
locales[0] = = Locale.GERMAN;
locales[1] = Locale.getDefault();
ftp.getAdvancedFTPSettings().setParserLocales(locales);


change directories

While you are connected to an FTP server, the server keeps track of your working directory. The server assumes you are referring to this directory whenever you perform a file operation without specifying an absolute path. In fact many FTP servers do not support the use of absolute paths.

The current working directory is available by calling the method:

string directory = ;

This may be changed using:

ftp.;

Or to simply go up to the parent directory:

ftp.;


upload, download and delete a file

Uploading, downloading and deletion of files is all done through simple method calls on the

Uploading Files

Uploading of a file is done by the following method-call:

ftp.;

This method uploads the file specified by the first argument and saves it on the server with the name specified by the second argument.  If the file is already present on the server then it is usually overwritten, though this depends on the server configuration.

File appending is also supported, whereby the contents of the local file are appended to the end of the remote file.  Appending is done by passing a third parameter to the uploadFile() method:

ftp.;

Downloading Files

Downloading of a file is done by the following method-call:

ftp.;

This method downloads the file specified by the second argument and saves it locally with the name specified by the first argument.  If the file is already present on the local storage medium then it is overwritten.

A remote file can also be downloaded into memory as a byte array:

ftp.;

Deleting Files

A file may be deleted by calling the method.

Notes:

(1) It is often useful to use streams to transfer data directly to and from memory. The topic explains how to do this.


use binary or ASCII mode

Files and data can be transferred in two different modes with all client classes - binary mode and ASCII mode. The transfer mode should always be set explicitly to ensure the correct mode is used.

Binary mode is the default for .

ASCII Mode

ASCII mode should be used when end-of-line character translation is required. When using ASCII mode, files are not transferred byte-for-byte. Instead, the newline character(s) on the source platform (e.g. in Windows, CR+LF) are replaced with the newline character(s) on the target platform (e.g. on Unix, LF). This means the source file may not be the same size as the end result if the platforms differ. If binary mode is used, for example, to transfer Unix text files to a Windows platform, many Windows text editors will not recognize the Unix newline characters, and the file will be difficult to read. To use ASCII mode, the method should be used, supplying the ASCII type as shown.

ftp.;

It's important to note that it is often acceptable to transfer text files in binary mode since most modern text editors are able to deal with UNIX and Windows end-of-line characters interchangably.  Furthermore, text files that appear to be ASCII files often contain "extended ASCII" characters which may be incompatible between different platforms.  It is therefore advisable to use binary mode unless end-of-line character translation is definitely required.


Binary Mode

Binary mode (a.k.a. image mode) should be used whenever no end-of-line translation is required.  In binary mode, the file is transferred byte-for-byte, i.e. an exact copy of the file or data is transferred. Typically, binary mode is used for files such as executables, compressed files, media files and non-text document formats such as OpenOffice or Microsoft Office files. To use binary mode, the method should be used, supplying the BINARY type as shown.

ftp.;



use active or passive mode

In the FTP protocol, data transfers are made on a different connection to the control connection - and a new connection is made for each data transfer or directory listing.

Data connections can be made in two different ways - the server initiating the connection (active mode) or the client initiating the connection (passive mode). For more discussion on connect modes, see The connect mode has certain implications for FTP'ing through firewalls. If problems are experienced using one mode, the alternative mode should be tried.

Active Mode

To use active mode, the advanced settings object must be obtained via , followed by , supplying the ACTIVE mode as shown:

ftp.getAdvancedFTPSettings().setConnectMode(FTPConnectMode.ACTIVE);

In active mode, the client supplies the port number to which the server connects. This is normally a random port, but a port range can be specified (for example a permissable range that is configured in a firewall). Use the method to set the range, e.g.

ftp.getAdvancedFTPSettings().setActivePortRange(61500, 61510);

The port number being sent to the server can be found from the log file (in DEBUG mode), looking for the PORT command, e.g.

PORT 151,134,10,195,240,68

The first four numbers are the IP address, and the last two form the port number. To calculate the port number that the server will try to connect to, multiple the first port number by 256 (2^8), and then add the second port number. In the example it will be 240*(2^8) + 68, yielding a port number of 61508.

ASCII Mode

To use passive mode, the 
method should be used, supplying the PASV type as shown.

ftp.getAdvancedFTPSettings().setConnectMode(FTPConnectMode.PASV);

If problems are being experienced with file transfers and directory listings (both of which use a new data connection each time), it is likely that a firewall is preventing the creation of the data connection. Try swapping from active to passive modes, or vice versa.


transfer using FTP streams

One of the advantages of integrating FTP functionality directly into a product rather than using stand-alone FTP applications is that data can be transferred directly to and from memory. This is particularly useful when transferring dynamic content needs, such as the results of database queries and other application data.

allows users to use InputStreams and OutputStreams to read and write to FTP servers, in the same way that a file or socket can be read from or written to. This is done using and methods.

To upload a string:

string s = "Hello world";
OutputStream out = ftp.uploadStream("Hello.txt");
try {
    out.write(s.getBytes());
}
finally {
    out.close();
}

It is essential to close the stream before performing any other FTP operations, as this completes the transfer.

Similarly, to download from an FTP server, an InputStream is used. This can be read and written anywhere:

StringBuffer s = new StringBuffer();
InputStream in = ftp.downloadStream("Hello.txt");
try {
    int ch = 0;
    while ((ch = in.read()) >= 0) {
        s.append((char)ch);
    }
}
finally {
    in.close();
}

Again, it is essential to close the stream before performing any other FTP operations.


monitor transfers and commands

It can be very useful to be able to monitor file transfers, that is, to receive programmatic feedback on how the transfer is progressing. Similarly, it can be useful to obtain the commands that are being sent back and forth. 

The interface is used for this purpose. Typically, the developer implements this interface in their own class (perhaps as an anonymous class). An instance is set via , and once the transfer begins, the instance is notified of the start and end of the transfer, as well as periodically during the transfer of how many bytes have been transferred so far. The commands sent back and forth to the server are also available.

The frequency of notifications of bytes transferred is controlled in the , via , which takes the number of bytes in between callbacks. Note that this value must be greater than the transfer buffer size, which can be changed via . This is because for efficiency, checks for the notification interval are only performed after each buffer has been transferred.

pause and resume transfers

At times network connections fail or processes are restarted, interrupting transfers. Also, it is sometimes necessary to terminate transfers, particularly for larger files that take a long time to transfer. 

In these cases, it is often desirable to resume transfers rather than starting them from scratch - especially for large files. This means only the remaining part of the file is subsequently uploaded or downloaded. 

Please note that resume is only supported for binary mode transfers. Because of line terminator translations, ASCII mode resumes are inpractical.

Invoking will cancel the currently executing transfer. To be able to call this method during a transfer will require a separate thread. Once this method is called, the transfer will cease once the current transfer buffer is emptied:

ftp.; // called from a different thread 

Cancelling a transfer may leave the connection to the server in an inconsistent state. After cancelling a transfer, it may be necessary to quit and reconnect to the server.

Once a transfer has been cancelled or has been interrupted, it can be resumed to complete the transfer. For resuming both uploads and downloads, it relies on examining the partially downloaded or uploaded file to see how many bytes remain to be transferred. The remaining bytes are then appended to the partial file. To perform a resume, simply upload or download the file again, supplying the parameter.

ftp.download(localFilename, remoteFilename, WriteMode.RESUME);

Because resuming relies only on the size of the partially downloaded or uploaded file, it does not matter how long ago the transfer failed or was terminated. As long as the partially transferred file is still available (and of course the original file to be transferred has not changed) , resuming the transfer will work correctly.


set up logging

Often, it can be very helpful to look at edtFTPj/Free's extensive logging output if any problems are experienced communicating with FTP servers. edtFTPj/Free has a powerful logging API modelled on the popular log4j library – in fact full integration with log4j is supported.

All commands sent to the FTP server and subsequent replies are logged, and can be made available on the console or directed to a log file. Much other useful information is also logged.

Statements within edtFTPj/Free are logged at different levels, ranging from least verbose (FATAL), to most verbose (DEBUG). Intermediate levels are ERROR, WARN, and INFO. An overall level can be set for the library, and all statements up to and including that level will be outputted.

For example, if the overall level is set to INFO then FATAL, ERROR, WARN and INFO log statements will be outputted, but DEBUG statements will not be.

There are also two additional levels that can be conveniently used - OFF which means no logging will occur, and ALL which means all log statements will be outputted, no matter what level they are. The ALL level is actually an additional level which is used for extremely verbose output - so when the level is set to ALL more log statements may be outputted than at  DEBUG.

Logging levels are encapsulated in the class. For example, the WARN level is represented by Level.WARN. 

By default, the log level is switched to OFF, so that no logging will appear.

The log level can be changed in two ways. Firstly, it can be changed explicitly by calling the
method on the class. For example:

Logger.(Level.);

will set the global logging level to DEBUG.

A System property, edtftp.log.level, can also be used to set the logging level. For example, using the -D option to set an application's System property, you could use:

java -Dedtftp.log.level=INFO com.mypackage.myclass

Using edtFTPj/Free's logging in your own application is very similar to using log4j. A logger is created, and its methods used to write logging information. Rather than use the Level class, the Logger class has convenience methods for logging at each level. An example is shown below:

Logger log = Logger.getLogger(MyClass.class);
log.info("Connecting to server " + host);

Logging to a file

As noted, all logging by default goes to standard output. A must be added if logging is to go to a file (and this will disable logging to standard out). An example is shown below:

Logger.(new FileAppender(myLogFileName));

Now all logging output will go to the FileAppender's file, and no logging will go to standard output. Multiple FileAppenders can be added. If the is added to the Logger as well, logging will be directed to the file and to standard output.

Log4j integration

Full integration with log4j is possible. A System property, edtftp.log.log4j, is used to indicate that log4j integration should be attempted. It must be set to “true”. Also, the log4j jar file must be available in the CLASSPATH. Once this is done all logging calls are directed via log4j, using reflection, and the standard log4j settings are used. More details on log4j can be found at the log4j site listed in the references.




阅读(2484) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~