2016-09-05 22 views
0

我正在使用Apache Commons Net(v3.5)和Java 8连接到远程FTPS站点(即在Internet上)。我能够轻松地连接到我的Windows 10机器上的FileZilla客户端,但是我的Java程序无法完成相同的步骤。我搜索了高低,但找不到根本原因。这里是我已经确认的事情:Java FTPS无法检索文件列表(FileZilla Client工作正常)

  • 我确保Java FTP命令的顺序与FileZilla客户端完全相同。
  • 我禁用了PC上的Windows防火墙和防病毒软件
  • 我重新启用了Windows防火墙并启用了日志记录功能。当使用FileZilla时,Windows防火墙日志列出了建立被动模式连接时的TCP连接。我没有看到Java程序的这种入口。
  • 我在PC上安装了FileZilla服务器。在我取消选中“使用PROT P时需要TLS会话恢复数据连接”后,java程序才起作用。 Java的例外情况不同,所以我不认为这是一支吸烟枪。
  • 我成功地在test.rebex.com服务器上运行了相同的代码。

下面是代码和任何想法是极大的赞赏:

import java.io.IOException; 
import java.io.PrintWriter; 
import org.apache.commons.net.PrintCommandListener; 
import org.apache.commons.net.ftp.FTP; 
import org.apache.commons.net.ftp.FTPFile; 
import org.apache.commons.net.ftp.FTPReply; 
import org.apache.commons.net.ftp.FTPSClient; 

public class testProgram { 

    public static void main(String[] args) { 

    String ftpServer = "ftp.domain.com"; 
    String ftpUsername = "[email protected]"; 
    String ftpPassword = "********"; 

    FTPSClient ftp = null; 

    // CONNECT TO THE SERVER 
    try { 
     // I have tried "SSL" as the argument, but same result 
     ftp = new FTPSClient(); 
     ftp.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out))); 

     ftp.connect(ftpServer,21); 

     int reply = ftp.getReplyCode(); 

     if (!FTPReply.isPositiveCompletion(reply)) { 
      ftp.disconnect(); 
      System.err.println("---------->FTP server refused connection.\n"); 

     } 

    } catch (Exception e) { 
     System.out.println(e.getMessage()); 
     e.printStackTrace(); 

    } 

    // LOGIN INTO SERVER 
    try { 
     if (!ftp.login(ftpUsername, ftpPassword)) { 
      ftp.logout(); 

     } else { 

      ftp.sendCommand("OPTS UTF8 ON");    
      ftp.execPBSZ(0);    
      ftp.execPROT("P"); 
      ftp.pwd(); 
      ftp.setFileType(FTP.BINARY_FILE_TYPE);  
      ftp.enterLocalPassiveMode(); 

      /* The next command always fails. 

       The FTP Server responds with "150 Accepted data connection" then: 

       org.apache.commons.net.ftp.FTPConnectionClosedException: Connection closed without indication. 
       at org.apache.commons.net.ftp.FTP.__getReply(FTP.java:316) 
       at org.apache.commons.net.ftp.FTP.__getReply(FTP.java:292) 
       at org.apache.commons.net.ftp.FTP.getReply(FTP.java:712) 
       at org.apache.commons.net.ftp.FTPClient.completePendingCommand(FTPClient.java:1857) 
       at org.apache.commons.net.ftp.FTPClient.listNames(FTPClient.java:2919) 
       at org.apache.commons.net.ftp.FTPClient.listNames(FTPClient.java:2952) 
       at myPackage.testProgram.main(testProgram.java:78) 

       I have tried other commands, but it disconnects here... 
      */ 

      FTPFile[] ftpFiles = ftp.listFiles(); 
      System.out.println("---------->Number of Files = " + ftpFiles.length); 
      ftp.logout(); 

     } 
    } catch (Exception e) { 

     e.printStackTrace(); 
    } 

    //Ensure Disconnected at the end. 
    if (ftp.isConnected()) { 
     try { 
      ftp.disconnect(); 
     } catch (IOException f) { 
      // do nothing 
     } 

    } 
    } 
} 

这是从我的电脑上的FileZilla Client日志:

2016-09-06 09:09:50 4756 1 Status: Resolving address of ftp.domain.com 
2016-09-06 09:09:51 4756 1 Status: Connecting to h1.h2.h3.h4:21... 
2016-09-06 09:09:51 4756 1 Status: Connection established, waiting for welcome message... 
2016-09-06 09:09:51 4756 1 Response: 220---------- Welcome to Pure-FTPd [privsep] [TLS] ---------- 
2016-09-06 09:09:51 4756 1 Response: 220-You are user number 2 of 50 allowed. 
2016-09-06 09:09:51 4756 1 Response: 220-Local time is now 13:09. Server port: 21. 
2016-09-06 09:09:51 4756 1 Response: 220-This is a private system - No anonymous login 
2016-09-06 09:09:51 4756 1 Response: 220-IPv6 connections are also welcome on this server. 
2016-09-06 09:09:51 4756 1 Response: 220 You will be disconnected after 15 minutes of inactivity. 
2016-09-06 09:09:51 4756 1 Command: AUTH TLS 
2016-09-06 09:09:51 4756 1 Response: 234 AUTH TLS OK. 
2016-09-06 09:09:51 4756 1 Status: Initializing TLS... 
2016-09-06 09:09:51 4756 1 Status: Verifying certificate... 
2016-09-06 09:09:51 4756 1 Status: TLS connection established. 
2016-09-06 09:09:51 4756 1 Command: USER [email protected] 
2016-09-06 09:09:51 4756 1 Response: 331 User [email protected] OK. Password required 
2016-09-06 09:09:51 4756 1 Command: PASS ************* 
2016-09-06 09:09:51 4756 1 Response: 230 OK. Current restricted directory is/
2016-09-06 09:09:51 4756 1 Command: SYST 
2016-09-06 09:09:51 4756 1 Response: 215 UNIX Type: L8 
2016-09-06 09:09:51 4756 1 Command: FEAT 
2016-09-06 09:09:51 4756 1 Response: 211-Extensions supported: 
2016-09-06 09:09:51 4756 1 Response: EPRT 
2016-09-06 09:09:51 4756 1 Response: IDLE 
2016-09-06 09:09:51 4756 1 Response: MDTM 
2016-09-06 09:09:51 4756 1 Response: SIZE 
2016-09-06 09:09:51 4756 1 Response: MFMT 
2016-09-06 09:09:51 4756 1 Response: REST STREAM 
2016-09-06 09:09:51 4756 1 Response: MLST type*;size*;sizd*;modify*;UNIX.mode*;UNIX.uid*;UNIX.gid*;unique*; 
2016-09-06 09:09:51 4756 1 Response: MLSD 
2016-09-06 09:09:51 4756 1 Response: AUTH TLS 
2016-09-06 09:09:51 4756 1 Response: PBSZ 
2016-09-06 09:09:51 4756 1 Response: PROT 
2016-09-06 09:09:51 4756 1 Response: UTF8 
2016-09-06 09:09:51 4756 1 Response: TVFS 
2016-09-06 09:09:51 4756 1 Response: ESTA 
2016-09-06 09:09:51 4756 1 Response: PASV 
2016-09-06 09:09:51 4756 1 Response: EPSV 
2016-09-06 09:09:51 4756 1 Response: SPSV 
2016-09-06 09:09:51 4756 1 Response: ESTP 
2016-09-06 09:09:51 4756 1 Response: 211 End. 
2016-09-06 09:09:51 4756 1 Command: OPTS UTF8 ON 
2016-09-06 09:09:51 4756 1 Response: 200 OK, UTF-8 enabled 
2016-09-06 09:09:51 4756 1 Command: PBSZ 0 
2016-09-06 09:09:51 4756 1 Response: 200 PBSZ=0 
2016-09-06 09:09:51 4756 1 Command: PROT P 
2016-09-06 09:09:52 4756 1 Response: 200 Data protection level set to "private" 
2016-09-06 09:09:52 4756 1 Status: Logged in 
2016-09-06 09:09:52 4756 1 Status: Retrieving directory listing... 
2016-09-06 09:09:52 4756 1 Command: PWD 
2016-09-06 09:09:52 4756 1 Response: 257 "/" is your current location 
2016-09-06 09:09:52 4756 1 Command: TYPE I 
2016-09-06 09:09:52 4756 1 Response: 200 TYPE is now 8-bit binary 
2016-09-06 09:09:52 4756 1 Command: PASV 
2016-09-06 09:09:52 4756 1 Response: 227 Entering Passive Mode (h1,h2,h3,h4,133,150) 
2016-09-06 09:09:52 4756 1 Command: MLSD 
2016-09-06 09:09:52 4756 1 Response: 150 Accepted data connection 
2016-09-06 09:09:52 4756 1 Response: 226-Options: -a -l 
2016-09-06 09:09:52 4756 1 Response: 226 6 matches total 

使用麦克的建议,我打开了TLS调试。它看起来程序再次通过TLS握手。输出很长,但在发出list命令后,我看到“*** ClientHello,TLSv1.2”以及与启动FTP连接相同的命令。

的差异似乎来结尾:

%% Cached client session: [Session-2, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256] 
main, received EOFException: ignored 
main, called closeInternal(false) 
main, SEND TLSv1.2 ALERT: warning, description = close_notify 
main, WRITE: TLSv1.2 Alert, length = 26 
main, called closeSocket(false) 
main, called close() 
main, called closeInternal(true) 
main, called close() 
main, called closeInternal(true) 
main, received EOFException: ignored 
main, called closeInternal(false) 
main, SEND TLSv1.2 ALERT: warning, description = close_notify 
main, WRITE: TLSv1.2 Alert, length = 26 
main, called closeSocket(false) 
org.apache.commons.net.ftp.FTPConnectionClosedException: Connection closed without indication. 
+0

对于初学者来说,你的try块太长了。将你的代码拆分成不同的try/catch块,并且不要捕获Exception,这是一个死亡陷阱。另外,从来没有'.printStackTrace()';那有什么用处?行动例外 – fge

+0

@fge定义'太长'。 '将代码分解到不同的try/catch块'为什么?这个建议只是货真价实的编程。 try/catch块必须足够长以包含所有依赖于它的代码。 – EJP

+0

我愿意承认示例代码应该远远“更清洁”,但我也知道try-catch块没有任何解决问题。我清楚地显示了异常情况发生的位置。 – SpartanXL01

回答

2

虽然这看起来像一个老帖子,我面临着类似的问题,今天无法弄清楚(最初)的解决方案。我可以通过FileZilla中,但不与FTPSClient和运行ftpClient.enterLocalPassiveMode()连接后,经常拿425 cannot open data connection

我的解决办法是登录前,但连接到的FTPServer后改变ftpClient.enterLocalPassiveMode()和它的工作。通常,我看到的所有代码示例在发送/接收数据之前使用enterlocalpassivemode,但在登录之后。请参阅下面的代码,了解适用于我的示例。

FTPSClient ftpClient = new FTPSClient(false); 
ftpClient.connect("remote.ftp.server", port); 
ftpClient.enterLocalPassiveMode();// Run the passive mode command now instead of after loggin in. 
ftpClient.login("username", "password"); 
ftpClient.execPBSZ(0); 
ftpClient.execPROT("P"); 
ftpClient.type(FTP.BINARY_FILE_TYPE); 
//ftpClient.enterLocalPassiveMode(); Previously it was here. 
FTPFile[] files = ftpClient.listDirectories("/"); 

希望这会有所帮助。还请注意,所有其他的代码和良好做法都被省略以缩短答案。