这两天一直在为一个FTP上传文件的项目纠结
以前的员工用sun.net.ftp.FtpClient写了一个上传文件项目,经常出现小问题,公司要求优化,并将
sun.net.ftp.FtpClient 改成apache的FtpClient
代码修改以后apache FtpClient 能够登陆,
ftp.login(user, pass) 成功
但是其它操作ftp.listNames(),storeFile 一执行就报错
java.net.SocketException: Connection reset
开始我以为是 主被动模式问题
当前用的jdk1.6版本 这个版本的sun.net.ftp.FtpClient只有被动模式
我确认我的代码中有加入 ftp.enterLocalActiveMode();
我尝试换成主动模式试了,肯定还是不行,服务器根本不会主动连接我的ftp客户端
(对方服务器配置的就是被动模式)
再次分析问题,
1.sun.net.ftp.FtpClient可以连接并上传文件
2.apache的FtpClient 可以login成功
3.异常报错指向apache的FtpClient PASV()这个方法
4.我尝试直接使用ftp协议pasv 立刻就提示 java.net.SocketException: Connection reset
难道sun.net.ftp.FtpClient没有运行PASV指令 ?
于是我查看了sun.net.ftp.FtpClient源码,果然其中有一段
if (issueCommand("EPSV ALL") == FTP_SUCCESS)
{
if (issueCommand("EPSV") == FTP_ERROR){
....
} else {
if (issueCommand("PASV") == FTP_ERROR)
它先执行的是EPSV ALL
回过头来查询apacheClient 源码
boolean attemptEPSV = (isUseEPSVwithIPv4()) || (isInet6Address);
if ((attemptEPSV) && (epsv() == 229))
{
__parseExtendedPassiveModeReply((String)this._replyLines.get(0));
}
else
{
if (isInet6Address) {
return null;
}
if (pasv() != 227) {
return null;
}
原来如此
修改代码加上ftp.setUseEPSVwithIPv4(true);
终于文件上传成功了.
注意 我用的是 commons-net-3.0.jar
为什么PASV不能执行,继续找ing....