📄 ftpclient.java
字号:
if (monitor != null && monitorCount > monitorInterval) {
monitor.bytesTransferred(size);
monitorCount = 0;
}
}
}
catch (IOException ex) {
storedEx = ex;
}
finally {
out.close();
}
closeDataSocket();
// if we failed to write to the stream, rethrow the exception
if (storedEx != null)
throw storedEx;
else if (monitor != null)
monitor.bytesTransferred(size);
// log bytes transferred
log.debug("Transferred " + size + " bytes from remote host");
}
/**
* Get data from the FTP server. Transfers in
* whatever mode we are in. Retrieve as a byte array. Note
* that we may experience memory limitations as the
* entire file must be held in memory at one time.
*
* @param remoteFile name of remote file in
* current directory
*/
public byte[] get(String remoteFile)
throws IOException, FTPException {
initGet(remoteFile);
// get an input stream to read data from
BufferedInputStream in =
new BufferedInputStream(
new DataInputStream(data.getInputStream()));
// B. McKeown:
// If we are in active mode we have to set the timeout of the passive
// socket. We can achieve this by calling setTimeout() again.
// If we are in passive mode then we are merely setting the value twice
// which does no harm anyway. Doing this simplifies any logic changes.
data.setTimeout(timeout);
// do the retrieving
long size = 0;
long monitorCount = 0;
byte [] chunk = new byte[transferBufferSize]; // read chunks into
byte [] resultBuf = null; // where we place result
ByteArrayOutputStream temp =
new ByteArrayOutputStream(transferBufferSize); // temp swap buffer
int count; // size of chunk read
// read from socket & write to file
while ((count = readChunk(in, chunk, transferBufferSize)) >= 0 && !cancelTransfer) {
temp.write(chunk, 0, count);
size += count;
monitorCount += count;
if (monitor != null && monitorCount > monitorInterval) {
monitor.bytesTransferred(size);
monitorCount = 0;
}
}
temp.close();
// get the bytes from the temp buffer
resultBuf = temp.toByteArray();
closeDataSocket();
// notify final transfer size
if (monitor != null)
monitor.bytesTransferred(size);
validateTransfer();
return resultBuf;
}
/**
* Run a site-specific command on the
* server. Support for commands is dependent
* on the server
*
* @param command the site command to run
* @return true if command ok, false if
* command not implemented
*/
public boolean site(String command)
throws IOException, FTPException {
checkConnection(true);
// send the retrieve command
FTPReply reply = control.sendCommand("SITE " + command);
// Can get a 200 (ok) or 202 (not impl). Some
// FTP servers return 502 (not impl)
String[] validCodes = {"200", "202", "502"};
lastValidReply = control.validateReply(reply, validCodes);
// return true or false? 200 is ok, 202/502 not
// implemented
if (reply.getReplyCode().equals("200"))
return true;
else
return false;
}
/**
* List a directory's contents
*
* @param dirname the name of the directory (<b>not</b> a file mask)
* @return a string containing the line separated
* directory listing
* @deprecated As of FTP 1.1, replaced by {@link #dir(String)}
*/
public String list(String dirname)
throws IOException, FTPException {
return list(dirname, false);
}
/**
* List a directory's contents as one string. A detailed
* listing is available, otherwise just filenames are provided.
* The detailed listing varies in details depending on OS and
* FTP server.
*
* @param dirname the name of the directory(<b>not</b> a file mask)
* @param full true if detailed listing required
* false otherwise
* @return a string containing the line separated
* directory listing
* @deprecated As of FTP 1.1, replaced by {@link #dir(String,boolean)}
*/
public String list(String dirname, boolean full)
throws IOException, FTPException {
String[] list = dir(dirname, full);
StringBuffer result = new StringBuffer();
String sep = System.getProperty("line.separator");
// loop thru results and make into one string
for (int i = 0; i < list.length; i++) {
result.append(list[i]);
result.append(sep);
}
return result.toString();
}
/**
* Override the chosen file factory with a user created one - meaning
* that a specific parser has been selected
*
* @param fileFactory
*/
public void setFTPFileFactory(FTPFileFactory fileFactory) {
this.fileFactory = fileFactory;
}
/**
* Set the locale for date parsing of dir listings
*
* @param locale new locale to use
*/
public void setParserLocale(Locale locale) {
listingLocale = locale;
}
/**
* List a directory's contents as an array of FTPFile objects.
* Should work for Windows and most Unix FTP servers - let us know
* about unusual formats (http://www.enterprisedt.com/forums/index.php)
*
* @param dirname name of directory OR filemask
* @return an array of FTPFile objects
*/
public FTPFile[] dirDetails(String dirname)
throws IOException, FTPException, ParseException {
// create the factory
if (fileFactory == null)
fileFactory = new FTPFileFactory(system());
fileFactory.setLocale(listingLocale);
// get the details and parse
return fileFactory.parse(dir(dirname, true));
}
/**
* List current directory's contents as an array of strings of
* filenames.
*
* @return an array of current directory listing strings
*/
public String[] dir()
throws IOException, FTPException {
return dir(null, false);
}
/**
* List a directory's contents as an array of strings of filenames.
*
* @param dirname name of directory OR filemask
* @return an array of directory listing strings
*/
public String[] dir(String dirname)
throws IOException, FTPException {
return dir(dirname, false);
}
/**
* List a directory's contents as an array of strings. A detailed
* listing is available, otherwise just filenames are provided.
* The detailed listing varies in details depending on OS and
* FTP server. Note that a full listing can be used on a file
* name to obtain information about a file
*
* @param dirname name of directory OR filemask
* @param full true if detailed listing required
* false otherwise
* @return an array of directory listing strings
*/
public String[] dir(String dirname, boolean full)
throws IOException, FTPException {
checkConnection(true);
// set up data channel
data = control.createDataSocket(connectMode);
data.setTimeout(timeout);
// send the retrieve command
String command = full ? "LIST ":"NLST ";
if (dirname != null)
command += dirname;
// some FTP servers bomb out if NLST has whitespace appended
command = command.trim();
FTPReply reply = control.sendCommand(command);
// check the control response. wu-ftp returns 550 if the
// directory is empty, so we handle 550 appropriately. Similarly
// proFTPD returns 450
String[] validCodes1 = {"125", "150", "450", "550"};
lastValidReply = control.validateReply(reply, validCodes1);
// an empty array of files for 450/550
String[] result = new String[0];
// a normal reply ... extract the file list
String replyCode = lastValidReply.getReplyCode();
if (!replyCode.equals("450") && !replyCode.equals("550")) {
// get a character input stream to read data from .
LineNumberReader in =
new LineNumberReader(
new InputStreamReader(data.getInputStream()));
// read a line at a time
Vector lines = new Vector();
String line = null;
while ((line = readLine(in)) != null) {
lines.addElement(line);
}
closeDataSocket();
// check the control response
String[] validCodes2 = {"226", "250"};
reply = control.readReply();
lastValidReply = control.validateReply(reply, validCodes2);
// empty array is default
if (!lines.isEmpty()) {
result = new String[lines.size()];
lines.copyInto(result);
}
}
else { // 450 or 550 - still need to close data socket
closeDataSocket();
}
return result;
}
/**
* Attempts to read a specified number of bytes from the given
* <code>InputStream</code> and place it in the given byte-array.
* The purpose of this method is to permit subclasses to execute
* any additional code necessary when performing this operation.
* @param in The <code>InputStream</code> to read from.
* @param chunk The byte-array to place read bytes in.
* @param chunksize Number of bytes to read.
* @return Number of bytes actually read.
* @throws IOException Thrown if there was an error while reading.
*/
protected int readChunk(BufferedInputStream in, byte[] chunk, int chunksize)
throws IOException {
return in.read(chunk, 0, chunksize);
}
/**
* Attempts to read a single character from the given <code>InputStream</code>.
* The purpose of this method is to permit subclasses to execute
* any additional code necessary when performing this operation.
* @param in The <code>LineNumberReader</code> to read from.
* @return The character read.
* @throws IOException Thrown if there was an error while reading.
*/
protected int readChar(LineNumberReader in)
throws IOException {
return in.read();
}
/**
* Attempts to read a single line from the given <code>InputStream</code>.
* The purpose of this method is to permit subclasses to execute
* any additional code necessary when performing this operation.
* @param in The <code>LineNumberReader</code> to read from.
* @return The string read.
* @throws IOException Thrown if there was an error while reading.
*/
protected String readLine(LineNumberReader in)
throws IOException {
return in.readLine();
}
/**
* Gets the latest valid reply from the server
*
* @return reply object encapsulating last valid server response
*/
public FTPReply getLastValidReply() {
return lastValidReply;
}
/**
* Get the current transfer type
*
* @return the current type of the transfer,
* i.e. BINARY or ASCII
*/
public FTPTransferType getType() {
return transferType;
}
/**
* Set the transfer type
*
* @param type the transfer type to
* set the server to
*/
public void setType(FTPTransferType type)
throws IOException, FTPException {
checkConnection(true);
// determine the character to send
String typeStr = FTPTransferType.ASCII_CHAR;
if (type.equals(FTPTransferType.BINARY))
typeStr = FTPTransferType.BINARY_CHAR;
// send the command
FTPReply reply = control.sendCommand("TYPE " + typeStr);
lastValidReply = control.validateReply(reply, "200");
// record the type
transferType = type;
}
/**
* Delete the specified remote file
*
* @param remoteFile name of remote file to
* delete
*/
public void delete(String remoteFile)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -