通过socket实现两台FTP服务器指定目录下的文件转移,其中包含了基础了ftp文件列表显示、上传和下载。这里仅供学习用,需掌握的点有socket、ftp命令、文件流读取转换等
完整代码如下:
FtpFileTransfer.java
package com.xxx.ftp.client; import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer; import com.xxx.ftp.model.ConnectInfo;
import com.xxx.ftp.model.FtpServerInfo; public class FtpFileTransfer { /**
* 文件转移
*
* @param source
* 源ftp文件目录
* @param dest
* 目标ftp文件目录
* @throws IOException
*/
public void transfer(FtpServerInfo source, FtpServerInfo dest) throws IOException {
// 源ftp目录下的文件列表
sendCommand(source.getConnect(), "CWD " + source.getDir());
sendCommand(source.getConnect(), "PASV");
String response = readNewMessage(source.getConnect());
String[] ipPort = getIPPort(response); String ip = ipPort[0];
int port = Integer.valueOf(ipPort[1]);
Socket dataSocket = new Socket(ip, port);
sendCommand(source.getConnect(), "LIST"); BufferedReader br = new BufferedReader(new InputStreamReader(dataSocket.getInputStream()));
// 读取源服务器的目录下所有文件名称
List<String> fileNameList = new ArrayList<String>();
String s = "";
while ((s = br.readLine()) != null) {
String fileInfo = new String(s.getBytes("ISO-8859-1"), "utf-8");
String[] arr = fileInfo.split("\\s+");
String fileName = arr[arr.length - 1];
fileNameList.add(fileName);
System.out.println(fileName);
} if (fileNameList.size() > 0) {
for (Iterator iterator = fileNameList.iterator(); iterator.hasNext();) {
// 根据文件名获取文件流
String fileName = (String) iterator.next();
sendCommand(source.getConnect(), "PASV");
response = readNewMessage(source.getConnect());
ipPort = getIPPort(response);
ip = ipPort[0];
port = Integer.valueOf(ipPort[1]);
Socket sourceDataSocket = new Socket(ip, port);
sendCommand(source.getConnect(), "RETR " + source.getDir() + "/" + fileName);
InputStream inputStream = sourceDataSocket.getInputStream(); // 文件流通过socket传输至目标ftp服务器文件目录下(输入流->输出流)
sendCommand(dest.getConnect(), "PASV");
response = readNewMessage(dest.getConnect());
ipPort = getIPPort(response);
ip = ipPort[0];
port = Integer.valueOf(ipPort[1]);
Socket destDataSocket = new Socket(ip, port);
sendCommand(dest.getConnect(), "STOR " + dest.getDir() + "/" + fileName);
OutputStream outputStream = destDataSocket.getOutputStream(); int offset;
byte[] bytes = new byte[1024];
while ((offset = inputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, offset);
}
inputStream.close();
outputStream.close();
dataSocket.close();
}
} System.out.println("transfer success!"); } /**
* ftp服务器连接
*
* @param ftpServerInfo
* ftp服务器信息 包含用户名 密码
* @return
* @throws IOException
*/
public ConnectInfo connect(FtpServerInfo ftpServerInfo) throws IOException {
Socket socket = new Socket(ftpServerInfo.getHost(), ftpServerInfo.getPort());
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); ConnectInfo connectInfo = new ConnectInfo();
connectInfo.setSocket(socket);
connectInfo.setWriter(writer);
connectInfo.setReader(reader); sendCommand(connectInfo, "USER " + ftpServerInfo.getUser());
sendCommand(connectInfo, "PASS " + ftpServerInfo.getPass());
return connectInfo;
} /**
* 断开ftp服务器连接
*
* @param connectInfo
* @throws IOException
*/
public void disconnect(ConnectInfo connectInfo) throws IOException {
if (connectInfo.getSocket() == null || !connectInfo.getSocket().isConnected()) {
return;
}
connectInfo.getSocket().close();
} /**
* 发送ftp命令
*
* @param connectInfo
* ftp服务器连接信息
* @param command
* ftp命令
* @throws IOException
*/
private void sendCommand(ConnectInfo connectInfo, String command) throws IOException {
if (command == null || command == "") {
return;
}
connectInfo.getWriter().write(command + "\r\n");
connectInfo.getWriter().flush();
} /**
* 根据连接读取ftp信息
*
* @param connect
* @return
* @throws IOException
*/
private String readNewMessage(ConnectInfo connect) throws IOException {
String response = null;
while (true) {
response = connect.getReader().readLine();
if (response == null || response.length() == 0) {
return null;
}
String rexp = "Entering Passive Mode";
if (response.contains(rexp)) {
break;
}
}
return response;
} /**
* 获取ip和端口
*
* @param response
* @return
* @throws IOException
*/
private String[] getIPPort(String response) throws IOException {
String[] ret = new String[2];
String ip = null;
int port = -1;
int opening = response.indexOf('(');
int closing = response.indexOf(')', opening + 1); if (closing > 0) {
String dataLink = response.substring(opening + 1, closing);
StringTokenizer tokenizer = new StringTokenizer(dataLink, ","); try {
ip = tokenizer.nextToken() + "." + tokenizer.nextToken() + "." + tokenizer.nextToken() + "."
+ tokenizer.nextToken();
port = Integer.parseInt(tokenizer.nextToken()) * 256 + Integer.parseInt(tokenizer.nextToken());
} catch (Exception e) {
throw new IOException("SimpleFTP received bad data link information: " + response);
}
}
ret[0] = ip;
ret[1] = String.valueOf(port);
return ret;
} public static void main(String[] args) throws IOException {
FtpFileTransfer ft = new FtpFileTransfer(); // 源ftp服务器
FtpServerInfo source = new FtpServerInfo();
source.setHost("192.168.11.129");
source.setUser("haoxr");
source.setPass("123456");
source.setDir("/home/haoxr/test");
ConnectInfo sourceConnectInfo = ft.connect(source);
source.setConnect(sourceConnectInfo); // 目标ftp服务器
FtpServerInfo dest = new FtpServerInfo();
dest.setHost("192.168.11.130");
dest.setUser("haoxr");
dest.setPass("123456");
dest.setDir("/home/haoxr/test");
ConnectInfo destConnectInfo = ft.connect(dest);
dest.setConnect(destConnectInfo); // 文件转移
ft.transfer(source, dest);
ft.disconnect(sourceConnectInfo);
ft.disconnect(destConnectInfo);
} }
ConnectInfo.java (javabean)
package com.xxx.ftp.model; import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.net.Socket; public class ConnectInfo { private Socket socket;
private BufferedReader reader;
private BufferedWriter writer; public Socket getSocket() {
return socket;
} public void setSocket(Socket socket) {
this.socket = socket;
} public BufferedReader getReader() {
return reader;
} public void setReader(BufferedReader reader) {
this.reader = reader;
} public BufferedWriter getWriter() {
return writer;
} public void setWriter(BufferedWriter writer) {
this.writer = writer;
} }
FtpServerInfo.java (javabean)
package com.xxx.ftp.model; public class FtpServerInfo { public FtpServerInfo() {
this.port = 21;
} private String host;
private int port;
private String user;
private String pass; private ConnectInfo connect; public ConnectInfo getConnect() {
return connect;
} public void setConnect(ConnectInfo connect) {
this.connect = connect;
} /** 文件目录 */
String dir; public String getHost() {
return host;
} public void setHost(String host) {
this.host = host;
} public int getPort() {
return port;
} public void setPort(int port) {
this.port = port;
} public String getUser() {
return user;
} public void setUser(String user) {
this.user = user;
} public String getPass() {
return pass;
} public void setPass(String pass) {
this.pass = pass;
} public String getDir() {
return dir;
} public void setDir(String file) {
this.dir = file;
} public static void main(String[] args) {
FtpServerInfo fs=new FtpServerInfo();
String pass=fs.getPass();
System.out.println(pass); fs=new FtpServerInfo();
fs.setPass("123456");
pass=fs.getPass(); System.out.println(pass);
} }