通过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 + " "); 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); } }