要运行ftp4j libraryQ你需要Java q行时环境v. 1.4+.
ftp4j JAR文gdC应用E序的classpath? 然后你就可以自动启用ftp4jcȝ使用?
可参?/span>ftp4j javadocs.
包中的主cLFTPClient (it.sauronsoftware.ftp4j.FTPClient).
创徏一?/span>FTPClient 实例Q?/p> q接q程FTP服务: 如果服务端口不是标准?1端口 (?FTPS?90端口)Q需要用port参数q行指定: ? 然后q行d程: 如果没有抛出M异常的话Q那么你通过q程服务器的认证?否则Q如果验证失败,你将会收?/span>it.sauronsoftware.ftp4j.FTPException异常. 匿名认证Q如果被q接服务认可的话Q?可通过发送用户名"anonymous" 和Q意密码来完成(注意Q有些服务器需要e-mail地址来代替密?: 使用q程FTP服务来做M事情Q然后再断开q接: q会向远E器发送FTP QUIT命o, 以进行一个合法断开程.如果你只是想中断q接而不惛_服务器发送Q何通知Q那么可以? 客户端通过q接器(一个承自it.sauronsoftware.ftp4j.FTPConnector的对?/em>Q来q接服务? 它将q回一个已l打开的连?一个实Cit.sauronsoftware.ftp4j.FTPConnection 接口的对?.q也是ؓ什么ftp4j 可以支持大量代理的原? 在连接远E服务器前,客户端实例可以用setConnector() Ҏ来设|连接器: 如果没有讄q接器的话,会用默认的q接?/span>DirectConnector (it.sauronsoftware.ftp4j.connectors.DirectConnector), 它实C对远E服务器的直接连接,且不会用代理?/p> 如果你只能通过代理来连接远E服务器, ftp4j包可以让你在下面的连接器中进行选择: 因ؓftp4j的连接器架构设计为可插拔的,因此你可以?/span>FTPConnector 抽象cL构徏自己的连接器. ftp4j包支持FTPS (隐式Z TLS/SSL的FTP) 和FTPES (昄ZTLS/SSL的FTP). setSecurity() Ҏ可用来打开q种Ҏ? 两个Ҏ都需要在q接q程服务器前调用. 如果安全协议讄成了SECURITY_FTPS, ?em>connect() Ҏ默认使用的端口ؓ990. 默认情况下,客户端对象商讨SSLq接会?/span>javax.net.ssl.SSLSocketFactory.getDefault()作ؓ其套接字工厂.可通过调用client.setSSLSocketFactory()Ҏ来改变默认套接字工厂. 另外一U?em style="background-color: inherit;">SSLSocketFactory, 可用来信任远E服务器颁发的证?谨慎使用): 获取当前目录的的l对路径Q此目录是FTP服务器的home目录Q? 改变目录: 你可以用绝对\径和相对路径: 回到父目? 要重命名q程文g或目? rename() Ҏ也可以用来从当前位置Ud文g或目录到其它位置. 在这个例子子Q假讑֜当前工作目录中,你有一个名?myfile.txt"的文?然后你想其Ud到子目录"myfolder"? 要删除远E文Ӟ需要调? 在这个例子中: 如果q程服务l你Z的话Q你可以在远E站点上创徏新目? 你也可以已存在的目录: 在这个例子中: h意,通常情况下,FTP 服务器只允许删除I目? FTP 协议q不会提供大量支持方法来获取工作目录的完整信?通常LIST命o会给你想知道的东西,但不辛的是,每个服务器会使用不同样式的响? q意味着某些服务器会q回UNIX样式的目录,有些服务器会q回DOS样式的目?其它的服务器又会使用别的样式. ftp4j 包可以处理许多的LIST响应格式, q将它们构徏成统一目录内容的结构对象表C?/span>.当前ftp4j可以处理: q可以通过使用可插拔的parsers来完??/span>it.sauronsoftware.ftp4j.listparsers包含了用于处理上q样式的对象.大多数时_q些已经够用了?/p> 要列出当前工作目录下的文件或文g夹,可调? 如果你收CFTPListParseException (it.sauronsoftware.ftp4j.FTPListParseException) 异常Q这意味着服务器对LIST命oq回了不可理解的样式,卛_不是上述列出的样?因此Q你可以试使用listNames() ҎQ?但它q不?em style="background-color: inherit;">list()Ҏ有优?/em>.。ؓ了I补这U缺P你可以构Z自己?span style="line-height: 1.5; background-color: inherit;">LIST响应解析?以支持你遇到的样?你可以实?/span>FTPListParser (it.sauronsoftware.ftp4j.FTPListParser) 接口Q然后你可以在client?/span>addListParser()Ҏ使用此实?/em>. FTPFile (it.sauronsoftware.ftp4j.FTPFile) 对象提供了目录内容的表示Q包括文Ӟ子目录和q接. Ҏ服务器的响应QFTPFile对象的某些字D可以是null 的或者是无意义的.h查javadocs来了解细? ?/span>list() Ҏ中你也可以用文件过滤参?如: 如果q接服务器明支持MLSD命o, ftp4j会用其来代替基本的LIST命o。MLSD的响应事实更为标准,准确Q更易解?不幸的是Q不是所有服务器都支持这个命令,q且有些服务器支持得非常p糕.Zq些理由Q开发者可以控制ftp4j是否应该使用MLSD命oQ即通过调用FTPClient对象?/em>setMLSDPolicy()Ҏ. 合法的? FTPClient.MLSD_IF_SUPPORTED FTPClient.MLSD_ALWAYS FTPClient.MLSD_NEVER 例如Q?/span> 通常情况?/span>FTPFile对象会告诉你条目的最后修Ҏ?/em>, 但正如上面描q的Q这依赖于服务器发回的响?如果你需要最后的修改旉Q但你又不能通过list()Ҏ得到Q那么可以尝试这样做Q?/p> 下蝲q程文g最单的方式是调?/span>download(String, File) ҎQ?/p> 要上? 要在已有文g中上传追加内? q些是阻塞式调用:它们会在传输完成?或failed, ?aborted?才返? 此外同步锁是否由客户端来实施的,因ؓ在每个时间段内只允许有一个常规的FTP通信.在每个时间段内,你可以处理多个传输器Q即使用多个FTPClient 对象,每个都与服务器徏立一个私有连? 你可以?/span>FTPDataTransferListener (it.sauronsoftware.ftp4j.FTPDataTransferListener)对象来监控传?你可以自己实C? 现在像下面这h下蝲或上? 当client处理下蝲或上传时Q传输器可以被同一?/span>FTPClient对象的不同线E通过调用 abortCurrentDataTransfer() Ҏaborted. 此方法还需要一个boolean参数:true表示执行合法?/em>abortq程(卛_服务器发送ABOR命o), false表示实然关闭传输器,而不向服务器发送通知: 需要注意的是,list()?/em>listNames() Ҏ暗中包含了数据传输器Q因abortCurrentDataTransfer() Ҏ也可以用来中断其listq程. 当数据传输器?/span>download(), upload(), append(), list() and listNames() Ҏ中中断时Q将会抛?em style="background-color: inherit;">FTPAbortedException 下蝲和上传操作可通过restartAt 参数来重新恢? 此操作会文g的第1056个字节处l箋执行下蝲操作。第一个传输的字节是W?057? 其它 download(), upload() ?em style="background-color: inherit;">append()Ҏ的变U可以让你用流来替?/em>java.io.File对象.因此你可以在数据库,|络q接或其它流上来传输数据?/p> 客户端和服务器之间的数据传输通道是通过单独的网l连接来建立? 在传输通道建立期间Q服务器可以?/span>active?/em>passive?/em>. 服务器激zL据传输时Q工作如下: active模式需要你的client能够收到来自服务器的q接.如果你的client处于防火墙, 代理或这两者合之后,那么大部分时间都会出现问题,因ؓ它不能收到来外界的连? 下面?/span>passive数据传输模式Q?/p> 在passive模式中,客户端连接不要求能收到服务器的连接请? 在ftp4j中,你可以用下面的调用来切换active、passive模式: ftp4j client passive 标志的默认gؓtrue: 如果你没有调?em style="background-color: inherit;">setPassive(false) Q你的客L在每ơ传输前Q都会向服务器请求passive模式. 当?passive文g传输Ӟ服务器会提供一?IP地址和一个端口号.作ؓFTP规范的client,需要用给定的L号和端口q行q接.在商业环境中Q这U行为可能会l常带来问题Q因为NAT配置可能会阻止对IP地址的连?q就是ؓ什么FTP clients通常会忽略服务器q回的Q何IP地址Q进而在通信U\中用同LL来连接服务器.ftp4j的行Z赖于服务器因? 在active传输模式中,可以讄下面的系l属? ftp4j.activeDataTransfer.hostAddress ftp4j.activeDataTransfer.portRange ftp4j.activeDataTransfer.acceptTimeout 要设|系l属性,你可? 用一个或多个 -Dproperty=value参数来启动JVM.? 直接在代码中讄pȝ属性,? 你可以调用下面的Ҏ选择你传输的cd: 默认的TYPE_AUTO帔R ,会让client自动来挑选类?如果文g的扩展名是client能被识别的文本类型标讎ͼ那么它会选择文本传输器来执行. 文g扩展名是通过FTPTextualExtensionRecognizer (it.sauronsoftware.ftp4j.FTPTextualExtensionRecognizer) 实例来识别的. 默认扩展识别器是it.sauronsoftware.ftp4j.recognizers.DefaultTextualExtensionRecognizer, 会将下面的视为文本类? 你可通过实现FTPTextualExtensionRecognizer 接口来实C自己的识别器Q但你可以更喜欢使用 class ParametricTextualExtensionRecognizer(it.sauronsoftware.ftp4j.recognizers.ParametricTextualExtensionRecognizer)便利c? 有些服务器支持数据传输压~特性-MODE Z. 在传输大文gӞ此特性可以节省带?一旦clientq上服务器ƈ通过认证,可通过调用下面的方法来查是否支持压~: 如果服务器端支持压羃,可通过下面的调用来启用压羃: 在此调用之后Q后l的数据传输(下蝲Q上传,列D操作Q都被将压羃以节省带? 数据传输压羃可通过下面的调用来用: 也可以检查标记? h意:压羃数据传输只当压羃支持且启用了的情况下才会发生. 默认情况下,压羃是禁用的Q即便是服务器支持压~? 如果有需?可以昄地打开. 假设你的client什么事情都不做Q因为在{待用户输入. 通常情况下, FTP服务器会自动断开非活跃客L. Z避免时Q你可以发送NOOP命o. 当非z跃时发生Ӟ客户端也可以自动发送NOOPs. 默认情况下,此特性是用的。它可以?nbsp;setAutoNoopTimeout() Ҏ中设|超时时间时启用,q提供一个毫Uؓ单位的?? 使用此|client会在30U后发送一个NOOP命o. NOOP时可通过讄于{于0的值来用: 你可以像下面q样来发送站点特D命令: 你也可以发送自定义命o: sendSiteCommand() ?nbsp;sendCustomCommand() 都会q回一?em style="background-color: inherit;">FTPReply (it.sauronsoftware.ftp4j.FTPReply)对象.使用此对象,你可以检查服务器的响应代码和消息. ftp4j 包定义了五种cd的异?FTPClient client = new FTPClient();
client.connect("ftp.host.com");
client.connect("ftp.host.com", port);
client.connect("ftp.host.com", 8021);
client.login("carlo", "mypassword");
client.login("anonymous", "ftp4j");
client.disconnect(true);
client.disconnect(false);
使用代理q行q接
client.setConnector(anyConnectorYouWant);
它可以通过HTTP代理来进行连接,q支持CONNECTҎ.
它可以通过FTP代理q行q接,支持SITE和OPEN命o风格的苛刻远E主?其它cd的FTP代理,需?em style="background-color: inherit;">username@remotehost 认证Q且可以不用连接器Q因为它们对于客L来说是透明的?/li>
它可以通过SOCKS 4/4a代理q行q接.
它可以通过SOCKS 5代理q行q接.FTPS/FTPES 安全q接
client.setSecurity(FTPClient.SECURITY_FTPS); // 启用 FTPS
client.setSecurity(FTPClient.SECURITY_FTPES); // 启用 FTPES
import it.sauronsoftware.ftp4j.FTPClient;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
// ... TrustManager[] trustManager = new TrustManager[] { new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() { return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) { }
public void checkServerTrusted(X509Certificate[] certs, String authType) { } } };
SSLContext sslContext = null;
try { sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustManager, new SecureRandom());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
FTPClient client = new FTPClient();
client.setSSLSocketFactory(sslSocketFactory);
client.setSecurity(FTPClient.SECURITY_FTPS);
// or client.setSecurity(FTPClient.SECURITY_FTPES); // ...览q程站点
String dir = client.currentDirectory();
client.changeDirectory(newPath);
client.changeDirectory("/an/absolute/one");
client.changeDirectory("relative");client.changeDirectoryUp();
重命名文件和目录
client.rename("oldname", "newname");
Ud文g和文件家
client.rename("myfile.txt", "myfolder/myfile.txt");
删除文g
client.deleteFile(relativeOrAbsolutePath);
client.deleteFile("useless.txt");
创徏、删除目?/span>
client.createDirectory("newfolder");
client.deleteDirectory(absoluteOrRelativePath);
client.deleteDirectory("oldfolder");
列出文g、目录、连?/span>
FTPFile[] list = client.list();
FTPFile[] list = client.list("*.jpg");
client只在服务器明支持MLSD命oӞ才用MLSD命o. q是ftp4j默认的行?
clientL会用MLSD命o, 即便服务器没有明表明支持MLSD命o.
clientl不使用MLSD命o,即便服务器明表明支持MLSD命o.client.setMLSDPolicy(FTPClient.MLSD_NEVER);
获取文g、目录的最后修Ҏ?/span>
java.util.Date md = client.modifiedDate("filename.ext");
下蝲、上传文?/span>
client.download("remoteFile.ext", new java.io.File("localFile.ext"));
client.upload(new java.io.File("localFile.ext"));
client.append(new java.io.File("localFile.ext"));
import it.sauronsoftware.ftp4j.FTPDataTransferListener;
public class MyTransferListener implements FTPDataTransferListener {
public void started() {
// Transfer started
}
public void transferred(int length) {
// Yet other length bytes has been transferred since the last time this
// method was called
}
public void completed() {
// Transfer completed
}
public void aborted() {
// Transfer aborted
}
public void failed() {
// Transfer failed
}
}client.download("remoteFile.ext", new java.io.File("localFile.ext"), new MyTransferListener());
client.upload(new java.io.File("localFile.ext"), new MyTransferListener());
client.append(new java.io.File("localFile.ext"), new MyTransferListener());
client.abortCurrentDataTransfer(true); // Sends ABOR
client.abortCurrentDataTransfer(false); // Breaks abruptly
client.download("remoteFile.ext", new java.io.File("localFile.ext"), 1056);
Active ?passive 数据传输模式
client.setPassive(false); // Active mode
client.setPassive(true); // Passive mode
L地址.当服务器h执行与客Lq接Ӟclient会蟩转到l定地址的服务器. 此值应该是一个有效的IPv4地址Q如Q?em style="background-color: inherit;">178.12.34.167. 如果没有提供此|客户端会自动解析pȝ地址.但如果clientq行于LAN中,ZȀzL据传输,会使用带端口{发的路由器来q接外部服务?那么自动探测到的地址可能不是正确? 当系l有多个|络接口Ӟ也可能发生这U情?通常使用pȝ属性,可以解决q种问题
q接端口范围. client会在其中挑选一个来q行数据传输.此?必须?em style="background-color: inherit;">start-stop 形式 Q如6000-7000 表示client只会在给定范围内挑选一个端口来q接服务?默认情况下没有指定端口范?q表Cclient会挑选Q何一个可用的端口.
以毫Uؓ单位的连接超时时? 如果服务器不能在l定时旉内连接clientQ传输会?em style="background-color: inherit;">FTPDataTransferException异常而中?/em>.0DC永不超时。默认?0000 (?0U?.java -Dftp4j.activeDataTransfer.hostAddress=178.12.34.167 -Dftp4j.activeDataTransfer.portRange=6000-7000 -Dftp4j.activeDataTransfer.acceptTimeout=5000 MyClass
System.setProperty("ftp4j.activeDataTransfer.hostAddress", "178.12.34.167");
System.setProperty("ftp4j.activeDataTransfer.portRange", "6000-7000");
System.setProperty("ftp4j.activeDataTransfer.acceptTimeout", "5000");二进制和文本数据传输cd
数据传输的另一个核心概忉|binary ?/span>textual cd.当传传输的文件是二进制文件时Q它视Zq制,服务器会按原样存储。而文本数据传输会传输的文g视ؓ字符?会进行字W集转换. 假设你的client正运行Windowsq_上,而服务器q行UNIX?它们的默认字W集通常是不同的. client以文本类型来发送文件时Qclient会假设文件是按机器标准字W集来编码的Q因此在发送前Q它会解码每个字Wƈ其~码?中间字符? 服务器收到流后,在存储前Q会解码中间字符集,q将其编码ؓ机器默认的字W集.字节虽然被改变了Q但内容是相同的?/span>
client.setType(FTPClient.TYPE_TEXTUAL);
client.setType(FTPClient.TYPE_BINARY);
client.setType(FTPClient.TYPE_AUTO);
abc acgi aip asm asp c c cc cc com conf cpp
csh css cxx def el etx f f f77 f90 f90 flx
for for g h h hh hh hlb htc htm html htmls
htt htx idc jav jav java java js ksh list
log lsp lst lsx m m mar mcf p pas php pl pl
pm py rexx rt rt rtf rtx s scm scm sdml sgm
sgm sgml sgml sh shtml shtml spc ssi talk
tcl tcsh text tsv txt uil uni unis uri uris
uu uue vcs wml wmls wsc xml zsh
无论如何Q都不要忘记你的识别器讄在client?client.setTextualExtensionRecognizer(myRecognizer);
数据传输压羃
boolean compressionSupported = client.isCompressionSupported();
client.setCompressionEnabled(true);
client.setCompressionEnabled(false);
boolean compressionEnabled = client.isCompressionEnabled();
不做M事(NOOPing the serverQ?/span>
此命令不会做M事情Q但它会向服务器说明Q客L仍然q活着Q请重围时计数?调用如下:client.noop();
client.setAutoNoopTimeout(30000);
client.setAutoNoopTimeout(0);
|站Ҏ的自定义命o
FTPReply reply = client.sendSiteCommand("YOUR COMMAND");
FTPReply reply = client.sendCustomCommand("YOUR COMMAND");
FTPCodes (it.sauronsoftware.ftp4j.FTPCodes) 接口报告了一些通用的FTP响应代码,因此你可以用这些包中的某个来进行匹?异常处理
依赖于方法,q会报告抛出了一个FTP故障.你可以检查报告的错误码,使用FTPCodes 帔R来获取故障原因的详细信息.
q表CE服务器使用非法方式q行了应{? q与FTP是不兼容? q应该是非常|见?
q通常发生?em style="background-color: inherit;">list()ҎQ如果服务器发回的响应不能被客户端包中现有解析器q行的话Q就会抛出此U异?/em>
当数据传?(download, upload, but also list and listNames) 因网l连接错误失败时Q就会抛出此U异?
当数据传?(download, upload, but also list and listNames) 因客L发出中断hp|Ӟ抛出的异?