我在百度、google上找了很多,但都不好用,请各位高手给一个好用的
sun.net.ftp.FtpClient可以
apache的commons.ftp可以
总之用什么包都可以,只要实现能把ftp服务器上的文件夹下载下来就行,文件夹里包括多少文件和文件夹,以及文件夹里的文件夹和子文件,都下载,递归算法,自动覆盖本地路径中的同名文件和文件夹
sun.net.ftp.FtpClient可以
apache的commons.ftp可以
总之用什么包都可以,只要实现能把ftp服务器上的文件夹下载下来就行,文件夹里包括多少文件和文件夹,以及文件夹里的文件夹和子文件,都下载,递归算法,自动覆盖本地路径中的同名文件和文件夹
try {
FTPListParseEngine f = ftpClient.initiateListParsing(path);
while (f.hasNext()) {
FTPFile[] files = f.getNext(5);
for(FTPFile file:files){
disFile(file,path);
}
} } catch (IOException e) {
e.printStackTrace();
}
}
//使用Sun的FtpClient做FTP上传下载
import sun.net.*;
import sun.net.ftp.*;
import java.io.*;
import java.util.*;
/**
FTP远程命令列表<br>
USER PORT RETR ALLO DELE SITE XMKD CDUP FEAT<br>
PASS PASV STOR REST CWD STAT RMD XCUP OPTS<br>
ACCT TYPE APPE RNFR XCWD HELP XRMD STOU AUTH<br>
REIN STRU SMNT RNTO LIST NOOP PWD SIZE PBSZ<br>
QUIT MODE SYST ABOR NLST MKD XPWD MDTM PROT<br>
在服务器上执行命令,如果用sendServer来执行远程命令(不能执行本地FTP命令)的话,所有FTP命令都要加上\r\n<br>
ftpclient.sendServer("XMKD /test/bb\r\n"); //执行服务器上的FTP命令<br>
ftpclient.readServerResponse一定要在sendServer后调用<br>
nameList("/test")获取指目录下的文件列表<br>
XMKD建立目录,当目录存在的情况下再次创建目录时报错<br>
XRMD删除目录<br>
DELE删除文件<br>
* 针对FTP中的所有调用使用到文件名的地方请使用完整的路径名(绝对路径开始)。
*/public class FtpUtils {
private FtpClient ftpclient;
private String ipAddress;
private int port;
private String username;
private String password;
/**
* 构造函数
* @param ip String 机器IP
* @param port String 机器FTP端口号
* @param username String FTP用户名
* @param password String FTP密码
* @throws Exception
*/
public FtpUtils(String ip, int port, String username, String password) throws
Exception {
this.ipAddress = ip;
this.port = port;
this.ftpclient = new FtpClient(ipAddress, port);
this.username = username;
this.password = password;
}
/**
* 构造函数
* @param ip String 机器IP,默认端口为21
* @param username String FTP用户名
* @param password String FTP密码
* @throws Exception
*/
public FtpUtils(String ip, String username, String password) throws
Exception {
this(ip,21,username,password);
}
/**
* 登录FTP服务器
* @throws Exception
*/
public void login() throws Exception {
ftpclient.login(username, password);
} /**
* 退出FTP服务器
* @throws Exception
*/
public void logout() throws Exception {
//用ftpclient.closeServer()断开FTP出错时用下更语句退出
ftpclient.sendServer("QUIT\r\n");
int reply = ftpclient.readServerResponse(); //取得服务器的返回信息
}
/**
* 取得指定目录下的所有文件名,不包括目录名称
* 分析nameList得到的输入流中的数,得到指定目录下的所有文件名
* @param fullPath String
* @return ArrayList
* @throws Exception
*/
public ArrayList fileNames(String fullPath) throws Exception {
ftpclient.ascii(); //注意,使用字符模式
TelnetInputStream list = ftpclient.nameList(fullPath);
byte[] names = new byte[2048];//如果文件数目很多,有可能溢出
int bufsize = 0;
bufsize = list.read(names, 0, names.length); //从流中读取
list.close();
ArrayList namesList = new ArrayList();
int i = 0;
int j = 0;
while (i < bufsize ) {
if (names[i] == 10) { //字符模式为10,二进制模式为13
String tempName = new String(names, j, i - j);
namesList.add(tempName);
//j = i + 2; //上一次位置二进制模式
j = i + 1; //上一次位置字符模式
}
i = i + 1;
}
return namesList;
}
/**
* 在FTP服务器上建立指定的目录,当目录已经存在的情下不会影响目录下的文件,这样用以判断FTP
* 上传文件时保证目录的存在目录格式必须以"/"根目录开头
* @param pathList String
* @throws Exception
*/
public void buildRemoteDir(String pathList) throws Exception {
ftpclient.ascii();
StringTokenizer s = new StringTokenizer(pathList, "/"); //sign
int count = s.countTokens();
String pathName = "";
while (s.hasMoreElements()) {
pathName = pathName + "/" + (String) s.nextElement();
try {
ftpclient.sendServer("XMKD " + pathName + "\r\n");
} catch (Exception e) {
e = null;
}
int reply = ftpclient.readServerResponse();
}
ftpclient.binary();
}
/**
* 上传文件到FTP服务器,remote路径以FTP服务器的"/"开始,带文件名、
* 上传文件只能使用二进制模式,当文件存在时再次上传则会覆盖
* @param local String
* @param remote String
* @throws Exception
*/
public void upFile(String local, String remote) throws Exception {
buildRemoteDir(remote.substring(0, remote.lastIndexOf("/")));
ftpclient.binary(); //此行代码必须放在buildRemoteDir之后
TelnetOutputStream ftpOut = ftpclient.put(remote);
InputStream in = new FileInputStream(local);//
byte[] buf = new byte[204800];
int bufsize = 0;
while((bufsize = in.read(buf, 0, buf.length)) != -1){
ftpOut.write(buf, 0, bufsize);
}
in.close();
ftpOut.close();
}
public void buildLocalDir(String fullPath) throws Exception { if(fullPath.lastIndexOf("/")<=0)return;
String path=fullPath.substring(0,fullPath.lastIndexOf("/")); File f= new File(path);
if(!f.exists()){
f.mkdirs();
}
}
public void downFile(String remote,String local) throws Exception {
buildLocalDir(local);
ftpclient.binary(); //此行代码必须放在buildRemoteDir之后
OutputStream out=new FileOutputStream(new File(local));
TelnetInputStream ftpIn = ftpclient.get(remote);
byte[] buff=new byte[204800];
int len=0;
while((len=ftpIn.read(buff))!=-1){
out.write(buff,0,len);
}
out.close();
ftpIn.close();
}
public static void main(String args[])throws Exception{
FtpUtils upfile=new FtpUtils("192.168.187.130","root","1-1=0");
upfile.login();
List list=upfile.fileNames("/");
System.out.println(list);
upfile.upFile("FtpUtils.java","/root/xjs/test/FtpUtils.java" );
upfile.downFile("/root/xjs/2.txt","xjs/2.txt" );
upfile.logout();
}
}
/*
以sun开头的class不是java里面的标准类,而是sun公司自己的的class,因此,他们位于rt.jar当中。因此,jdk源代码中没有提供源文件。但是,可以用诸如jad之类的反编译工具进行反编译。
实际上,基本原理就是利用Socket和ServerSocket来发送遵守FTP协议的消息,与FTP服务器进行交互。
主要用到这么几个类:
sun.net.ftp.FtpClient extends sun.net.TransferProtocolClient
sun.net.TransferProtocolClient extends sun.net.NetworkClient
sun.net.TelnetInputStream extends FilterInputStream
sun.net.TelnetOutputStream extends BufferedOutputStream
因为是使用被动模式,因此,客户端要去连接服务端,
在FtpClient的源代码的openDataConnection(String s)方法中有这么一句:
serversocket = new ServerSocket(0, 1);也就是客户端随便选择一个空闲端口。
也就是说,sun的FtpClient不支持主动模式。
*/