001.
//使用Sun的FtpClient做FTP上传下载
002.
import
sun.net.*;
003.
import
sun.net.ftp.*;
004.
import
java.io.*;
005.
import
java.util.*;
006.
/**
007.
FTP远程命令列表<br>
008.
USER
PORT RETR ALLO DELE SITE XMKD CDUP FEAT<br>
009.
PASS
PASV STOR REST CWD STAT RMD XCUP OPTS<br>
010.
ACCT
TYPE APPE RNFR XCWD HELP XRMD STOU AUTH<br>
011.
REIN
STRU SMNT RNTO LIST NOOP PWD SIZE PBSZ<br>
012.
QUIT
MODE SYST ABOR NLST MKD XPWD MDTM PROT<br>
013.
在服务器上执行命令,如果用sendServer来执行远程命令(不能执行本地FTP命令)的话,所有FTP命令都要加上\r\n<br>
014.
ftpclient.sendServer("XMKD
/test/bb\r\n"); //执行服务器上的FTP命令<br>
015.
ftpclient.readServerResponse一定要在sendServer后调用<br>
016.
nameList("/test")获取指目录下的文件列表<br>
017.
XMKD建立目录,当目录存在的情况下再次创建目录时报错<br>
018.
XRMD删除目录<br>
019.
DELE删除文件<br>
020.
*
针对FTP中的所有调用使用到文件名的地方请使用完整的路径名(绝对路径开始)。
021.
*/
022.
023.
public
class
FtpUtils
{
024.
private
FtpClient
ftpclient;
025.
private
String
ipAddress;
026.
private
int
port;
027.
private
String
username;
028.
private
String
pass<a href="http://www.it165.net/edu/ebg/"
target=
"_blank"
class
=
"keylink"
>word</a>;
029.
/**
030.
*
构造函数
031.
*
@param ip String 机器IP
032.
*
@param port String 机器FTP端口号
033.
*
@param username String FTP用户名
034.
*
@param pass<a href="http://www.it165.net/edu/ebg/" target="_blank"
class="keylink">word</a> String FTP密码
035.
*
@throws Exception
036.
*/
037.
public
FtpUtils(String
ip, int
port,
String username, String password) throws
038.
Exception
{
039.
this
.ipAddress
= ip;
040.
this
.port
= port;
041.
this
.ftpclient
= new
FtpClient(ipAddress,
port);
042.
this
.username
= username;
043.
this
.password
= password;
044.
}
045.
/**
046.
*
构造函数
047.
*
@param ip String 机器IP,默认端口为21
048.
*
@param username String FTP用户名
049.
*
@param password String FTP密码
050.
*
@throws Exception
051.
*/
052.
public
FtpUtils(String
ip, String username, String password) throws
053.
Exception
{
054.
this
(ip,
21
,username,password);
055.
}
056.
/**
057.
*
登录FTP服务器
058.
*
@throws Exception
059.
*/
060.
public
void
login()
throws
Exception
{
061.
ftpclient.login(username,
password);
062.
}
063.
064.
/**
065.
*
退出FTP服务器
066.
*
@throws Exception
067.
*/
068.
public
void
logout()
throws
Exception
{
069.
//用ftpclient.closeServer()断开FTP出错时用下更语句退出
070.
ftpclient.sendServer(
"QUIT\r\n"
);
071.
int
reply
= ftpclient.readServerResponse(); //取得服务器的返回信息
072.
}
073.
/**
074.
*
取得指定目录下的所有文件名,不包括目录名称
075.
*
分析nameList得到的输入流中的数,得到指定目录下的所有文件名
076.
*
@param fullPath String
077.
*
@return ArrayList
078.
*
@throws Exception
079.
*/
080.
public
ArrayList
fileNames(String fullPath) throws
Exception
{
081.
ftpclient.ascii();
//注意,使用字符模式
082.
TelnetInputStream
list = ftpclient.nameList(fullPath);
083.
byte
[]
names = new
byte
[
2048
];
//如果文件数目很多,有可能溢出
084.
int
bufsize
= 0
;
085.
bufsize
= list.read(names, 0
,
names.length); //从流中读取
086.
list.close();
087.
ArrayList
namesList = new
ArrayList();
088.
int
i
= 0
;
089.
int
j
= 0
;
090.
while
(i
< bufsize ) {
091.
if
(names[i]
== 10
)
{ //字符模式为10,二进制模式为13
092.
String
tempName = new
String(names,
j, i - j);
093.
namesList.add(tempName);
094.
//j
= i + 2; //上一次位置二进制模式
095.
j
= i + 1
;
//上一次位置字符模式
096.
}
097.
i
= i + 1
;
098.
}
099.
return
namesList;
100.
}
101.
/**
102.
*
在FTP服务器上建立指定的目录,当目录已经存在的情下不会影响目录下的文件,这样用以判断FTP
103.
*
上传文件时保证目录的存在目录格式必须以"/"根目录开头
104.
*
@param pathList String
105.
*
@throws Exception
106.
*/
107.
public
void
buildRemoteDir(String
pathList) throws
Exception
{
108.
ftpclient.ascii();
109.
StringTokenizer
s = new
StringTokenizer(pathList,
"/"
);
//sign
110.
int
count
= s.countTokens();
111.
String
pathName = ""
;
112.
while
(s.hasMoreElements())
{
113.
pathName
= pathName + "/"
+
(String) s.nextElement();
114.
try
{
115.
ftpclient.sendServer(
"XMKD
"+
pathName + "\r\n"
);
116.
}
catch
(Exception
e) {
117.
e
= null
;
118.
}
119.
int
reply
= ftpclient.readServerResponse();
120.
}
121.
ftpclient.binary();
122.
}
123.
/**
124.
*
上传文件到FTP服务器,remote路径以FTP服务器的"/"开始,带文件名、
125.
*
上传文件只能使用二进制模式,当文件存在时再次上传则会覆盖
126.
*
@param local String
127.
*
@param remote String
128.
*
@throws Exception
129.
*/
130.
public
void
upFile(String
local, String remote) throws
Exception
{
131.
buildRemoteDir(remote.substring(
0
,
remote.lastIndexOf("/"
)));
132.
ftpclient.binary();
//此行代码必须放在buildRemoteDir之后
133.
TelnetOutputStream
ftpOut = ftpclient.put(remote);
134.
InputStream
in = new
FileInputStream(local);
//
135.
byte
[]
buf = new
byte
[
204800
];
136.
int
bufsize
= 0
;
137.
while
((bufsize
= in.read(buf, 0
,
buf.length)) != -1
){
138.
ftpOut.write(buf,
0
,
bufsize);
139.
}
140.
in.close();
141.
ftpOut.close();
142.
}
143.
public
void
buildLocalDir(String
fullPath) throws
Exception
{
144.
145.
if
(fullPath.lastIndexOf(
"/"
)<=
0
)
return
;
146.
String
path=fullPath.substring(0
,fullPath.lastIndexOf(
"/"
));
147.
148.
File
f= new
File(path);
149.
if
(!f.exists()){
150.
f.mkdirs();
151.
}
152.
}
153.
public
void
downFile(String
remote,String local) throws
Exception
{
154.
buildLocalDir(local);
155.
ftpclient.binary();
//此行代码必须放在buildRemoteDir之后
156.
OutputStream
out=new
FileOutputStream(
new
File(local));
157.
TelnetInputStream
ftpIn = ftpclient.get(remote);
158.
byte
[]
buff=new
byte
[
204800
];
159.
int
len=
0
;
160.
while
((len=ftpIn.read(buff))!=-
1
){
161.
out.write(buff,
0
,len);
162.
}
163.
out.close();
164.
ftpIn.close();
165.
}
166.
public
static
void
main(String
args[])throws
Exception{
167.
FtpUtils
upfile=new
FtpUtils(
"192.168.187.130"
,
"root"
,
"1-1=0"
);
168.
upfile.login();
169.
List
list=upfile.fileNames("/"
);
170.
System.out.println(list);
171.
upfile.upFile(
"FtpUtils.java"
,
"/root/xjs/test/FtpUtils.java"
);
172.
upfile.downFile(
"/root/xjs/2.txt"
,
"xjs/2.txt"
);
173.
upfile.logout();
174.
}
175.
}
176.
/*
177.
以sun开头的class不是java里面的标准类,而是sun公司自己的的class,因此,他们位于rt.jar当中。因此,jdk源代码中没有提供源文件。但是,可以用诸如jad之类的反编译工具进行反编译。
178.
实际上,基本原理就是利用Socket和ServerSocket来发送遵守FTP协议的消息,与FTP服务器进行交互。
179.
主要用到这么几个类:
180.
sun.net.ftp.FtpClient
extends sun.net.TransferProtocolClient
181.
sun.net.TransferProtocolClient
extends sun.net.NetworkClient
182.
sun.net.TelnetInputStream
extends FilterInputStream
183.
sun.net.TelnetOutputStream
extends BufferedOutputStream
184.
因为是使用被动模式,因此,客户端要去连接服务端,
185.
在FtpClient的源代码的openDataConnection(String
s)方法中有这么一句:
186.
serversocket
= new ServerSocket(0, 1);也就是客户端随便选择一个空闲端口。
187.
也就是说,sun的FtpClient不支持主动模式。
188.
*/