📄 ftpclient.java
字号:
package org.fife.net.ftp;
import java.io.*;
import java.net.*;
import java.util.*;
import org.fife.net.TelnetInputStream;
//import org.fife.net.TelnetOutputStream;
/**
* A very basic FTP client.
*
* @author Robert Futrell
* @version 0.5
*/
public class FTPClient {
private static final int TYPE_MIN = 0;
public static final int TYPE_ASCII = 0;
public static final int TYPE_IMAGE = 1;
public static final int TYPE_EBCDIC = 2;
private static final int TYPE_MAX = 2;
private String host;
private int port;
private boolean connected;
private Socket socket;
private BufferedInputStream inputStream;
private PrintStream outputStream;
private String lastReply;
private boolean replyPending;
private boolean binary;
private static final int DEFAULT_PORT = 21;
/*****************************************************************************/
/**
* Constructor.
*/
public FTPClient() {
replyPending = false;
binary = false;
}
/*****************************************************************************/
/**
* Changes to the specified directory on the remote FTP server.
*
* @param toDir The directory into which to move.
* @return Whether the command was successful. If this client isn't
* connected to an FTP server, <code>false</code> is returned.
* @throws IOException If an I/O error occurs.
*/
public boolean cd(String toDir) throws IOException {
if (!isConnected())
return false;
return !isErrorReply(issueCommand("CWD " + toDir));
}
/*****************************************************************************/
/**
* Opens a connection to an FTP server on the specified host. The FTP
* server is assumed to be on port 21.
*
* @param host The host to connect to.
* @throws IOException If an I/O exception occurs.
* @see #connect(String host, int port)
* @see #disconnect
*/
public void connect(String host) throws IOException {
connect(host, DEFAULT_PORT);
}
/*****************************************************************************/
/**
* Opens a connection to an FTP server on the specified host at the
* specified port.
*
* @param host The host to connect to.
* @param port The port on which the FTP server is running.
* @throws IOException If an I/O error occurs.
* @see #connect(String host)
* @see #disconnect
*/
public void connect(String host, int port) throws IOException {
this.host = host;
this.port = port;
if (isConnected())
disconnect();
socket = new Socket();
socket.connect(new InetSocketAddress(host, port));
outputStream = new PrintStream(new BufferedOutputStream(
socket.getOutputStream()), true);
inputStream = new BufferedInputStream(socket.getInputStream());
getReply(); // Get possible 220 msg about FTP server.
connected = true;
}
/*****************************************************************************/
/**
* Creates and returns a socket for the specified command.
*
* @param command The command.
* @return The socket.
* @throws IOException If an I/O error occurs.
*/
private Socket createSocketForCommand(String command) throws IOException {
ServerSocket s = new ServerSocket(0, 1);
Socket clientSocket = null;
try {
InetAddress address = s.getInetAddress();
if (address.isAnyLocalAddress())
address = socket.getLocalAddress();
String command2 = "PORT ";
byte[] addr = address.getAddress();
for (int i = 0; i < addr.length; i++)
command2 += (addr[i] & 0xFF) + ",";
command2 += ((s.getLocalPort() >>> 8) & 0xff) + ","
+ (s.getLocalPort() & 0xff);
int code = issueCommand(command2);
if (isErrorReply(code)) {
throw new IOException("PORT: " + getLastReply());
}
code = issueCommand(command);
if (isErrorReply(code)) {
throw new IOException(command + ":" + getLastReply());
}
clientSocket = s.accept();
} finally {
s.close();
}
return clientSocket;
}
/*****************************************************************************/
/**
* Deletes a file on the FTP server.
*
* @param fileName The file to delete.
* @return Whether the delete was successful. If this client is not
* connected to an FTP server, <code>false</code> is returned.
* @throws IOException If an I/O error occurs.
* @see #rmd
*/
public boolean dele(String fileName) throws IOException {
if (!isConnected())
return false;
return !isErrorReply(issueCommand("DELE " + fileName));
}
/*****************************************************************************/
/**
* Closes the current FTP connection by issuing a <code>QUIT</code>
* command.
*
* @throws IOException If an I/O error occurs.
* @see #connect(String host)
* @see #connect(String host, int port)
*/
public void disconnect() throws IOException {
issueCommand("QUIT");
socket.close();
inputStream = null;
outputStream = null;
connected = false;
}
/*****************************************************************************/
/**
* Returns an input stream for the specified file on the FTP server.
* If this client is not connected to an FTP server, <code>null</code>
* is returned.
*
* @param fileName The file to retrieve.
* @return An input stream for the file.
* @throws IOException If an I/O error occurs.
* @see #put
*/
public TelnetInputStream get(String fileName) throws IOException {
if (!isConnected())
return null;
Socket s = createSocketForCommand("RETR " + fileName);
return new TelnetInputStream(s.getInputStream(), isBinary());
}
/*****************************************************************************/
/**
* Returns the reply from the FTP server from the last action, as a
* string.
*
* @return The last reply received from the FTP server.
*/
public String getLastReply() {
return lastReply;
}
/*****************************************************************************/
/**
* Gets the reply from the server from a command.
*
* @return
* @throws IOException If an I/O error occurs.
*/
private int getReply() throws IOException {
int ch;
int code;
int codeToMatch = -1;
StringBuffer buf = new StringBuffer(80);
lastReply = "";
while (true) {
while ((ch=inputStream.read()) != -1) {
if (ch=='\r') {
if ((ch=inputStream.read()) != '\n')
buf.append('\r');
}
buf.append((char)ch);
if (ch=='\n')
break;
}
String reply = buf.toString();
buf.setLength(0);
lastReply += reply;
int length = reply.length();
if (length==0)
code = -1;
else if (length<3)
continue; // Need at least 3-digit reply code.
try {
code = Integer.parseInt(reply.substring(0,3));
} catch (NumberFormatException nfe) {
code = -1; // Should never happen.
}
if (codeToMatch!=-1) {
if (code!=codeToMatch ||
(length>3 && reply.charAt(3)=='-'))
continue;
break; // code==codeToMatch; no '-' => we're done.
}
else if (length>3 && reply.charAt(3)=='-') {
codeToMatch = code;
continue;
}
else
break;
} // End of while (true).
return code;
}
/*****************************************************************************/
/**
* Returns whether this FTP session is currently sending/receiving files
* in binary mode.
*
* @return Whether files are being transfered in binary mode.
* @see #type
*/
public boolean isBinary() {
return binary;
}
/*****************************************************************************/
/**
* Returns whether this client is connected to an FTP server. If it is
* not, then all attempted FTP operations (login, sending and receiving
* files, etc.) will fail.
*
* @return Whether this client is connected to an FTP server.
* @see #connect(String host)
* @see #connect(String host, int port)
*/
public boolean isConnected() {
return connected;
}
/*****************************************************************************/
/**
* Returns whether the specified FTP reply code represents an error.
*
* @return Whether the reply code represents an error.
*/
private static final boolean isErrorReply(int code) {
return (code/100)>=4;//==5;
}
/*****************************************************************************/
/**
* Returns whether the specified FTP reply code represents a "command
* in progress; real reply code coming later" message.
*
* @return Whether the specified reply code is a preliminary reply code.
*/
private static final boolean isPreliminaryReply(int code) {
return (code/100)==1;
}
/*****************************************************************************/
/**
* Issues an FTP command to the FtP server.
*
* @param command The command to issue.
* @return The 3-digit reply code corresponding to the response
* received from the server.
* @throws IOException If an I/O error occurs.
*/
private int issueCommand(String command) throws IOException {
int code;
while (replyPending) {
code = getReply();
replyPending = isPreliminaryReply(code);
}
outputStream.print(command + "\r\n");
code = getReply();
replyPending = isPreliminaryReply(code);
return code;
}
/*****************************************************************************/
/**
* Logs in to the FTP server as the specified user. If this FTP client
* is not connected to an FTP server, this method simply returns
* <code>false</code>.
*
* @param userID The user to log in as.
* @param password The password for the user.
* @return Whether the login was successful.
* @throws IOException If an I/O error occurs.
*/
public boolean login(String userID, String password) throws IOException {
if (isConnected()) {
int code = issueCommand("USER " + userID);
if (isErrorReply(code))
return false;
if (code==331) {
code = issueCommand("PASS " + password);
if (isErrorReply(code))
return false;
}
return true;
}
return false;
}
/*****************************************************************************/
/**
* Performs an "ls" command on the FTP server and returns its output.
*
* @return The result of the "ls" command.
* @throws IOException If an I/O error occurs.
*/
public TelnetInputStream ls() throws IOException {
return ls(".");
}
/*****************************************************************************/
/**
* Performs an "ls" command on the FTP server for the specified directory
* and returns its output. If this client is not connected to an FTP
* server or an error occurs, <code>null</code> is returned.
*
* @return The result of the "ls" command.
* @throws IOException If an I/O error occurs.
*/
public TelnetInputStream ls(String dir) throws IOException {
if (!isConnected())
return null;
Socket s = createSocketForCommand("LIST " + dir);
return new TelnetInputStream(s.getInputStream(), isBinary());
}
/*****************************************************************************/
/**
* Returns the current working directory of the FTP client. If this
* client isn't connected to an FTP server or an error occurs,
* <code>null</code> is returned.
*
* @return The current working directory.
* @throws IOException If an I/O error occurs.
*/
public String pwd() throws IOException {
if (!isConnected())
return null;
if (isErrorReply(issueCommand("PWD")))
return null;
return getLastReply(); // FIXME: Just grab directory, not full line!
}
/*****************************************************************************/
/**
* Removes a directory from an FTP server.
*
* @param dir The name of the directory to remove.
* @return Whether the directory was successfully removed. If this client
* is not connected to an FTP server, <code>false</code> is
* returned.
* @throws IOException If an I/O error occurs.
* @see #dele
*/
public boolean rmd(String dir) throws IOException {
if (!isConnected())
return false;
return !isErrorReply(issueCommand("RMD " + dir));
}
/*****************************************************************************/
/**
* Sets the type used in file transfer (e.g., "ASCII" or "IMAGE").
*
* @param type The type to use.
* @return Whether the command was successful.
* @throws IllegalArgumentException If <code>type</code> is not valid.
* @throws IOException If an I/O error occurs.
*/
public boolean type(int type) throws IOException {
if (type<TYPE_MIN || type>TYPE_MAX)
throw new IllegalArgumentException("Invalid type: " + type);
if (!isConnected())
return false;
String command = "TYPE ";
switch (type) {
case TYPE_ASCII:
command += "A";
break;
case TYPE_IMAGE:
command += "I";
break;
case TYPE_EBCDIC:
command += "E";
break;
}
boolean rc = !isErrorReply(issueCommand(command));
binary = (type==TYPE_IMAGE && rc);
return rc;
}
/*****************************************************************************/
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -