//使用Sun的FtpClient做FTP上传下载
import sun.net.*;
import sun.net.ftp.*;
import java.io.*;
import java.util.*;
/**
FTP远程命令列表
USER PORT RETR ALLO DELE SITE XMKD CDUP FEAT
PASS PASV STOR REST CWD STAT RMD XCUP OPTS
ACCT TYPE APPE RNFR XCWD HELP XRMD STOU AUTH
REIN STRU SMNT RNTO LIST NOOP PWD SIZE PBSZ
QUIT MODE SYST ABOR NLST MKD XPWD MDTM PROT
在服务器上执行命令,如果用sendServer来执行远程命令(不能执行本地FTP命令)的话,所有FTP命令都要加上\r\n
ftpclient.sendServer("XMKD /test/bb\r\n"); //执行服务器上的FTP命令
ftpclient.readServerResponse一定要在sendServer后调用
nameList("/test")获取指目录下的文件列表
XMKD建立目录,当目录存在的情况下再次创建目录时报错
XRMD删除目录
DELE删除文件
* 针对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不支持主动模式。
*/
阅读(11264) | 评论(0) | 转发(0) |