【问题标题】:android ftp file tranfer over explicit TLS通过显式 TLS 进行的 android ftp 文件传输
【发布时间】:2023-03-24 22:41:01
【问题描述】:

我在一遍又一遍地尝试让它工作后发布这个问题,但没有成功。 我尝试使用 apache commons 库在 android 中实现 FTP 文件传输。通信必须通过显式 TLS 身份验证来完成。 我可以成功登录,连接到服务器并列出文件,但是每当我尝试获取或存储文件时,我总是会遇到超时异常,超时值也非常大,即使对于 2Kb 的 txt 文件也是如此。 这是我的代码:

 FTPSClient ftpClient = new FTPSClient("TLS", false);
    ftpClient.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out)));
KeyManagerFactory kmf = getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(null, null);
KeyManager km = kmf.getKeyManagers()[0];
ftpClient.setKeyManager(km);
ftpClient.setBufferSize(1024 * 1024);
ftpClient.setConnectTimeout(900000);
ftpClient.connect(InetAddress.getByName("server ip address"), 990);
// Set protection buffer size
ftpClient.execPBSZ(0);
// // Set data channel protection to private
ftpClient.execPROT("P");
ftpClient.login("user", "password");
ftpClient.changeWorkingDirectory("/");
ftpClient.setSoTimeout(900000);
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
ftpClient.enterLocalPassiveMode();
buffIn = new BufferedInputStream(new FileInputStream(file.getAbsolutePath()));

//this works
FTPFile[] files = ftpClient.listFiles();
final OutputStream os = new FileOutputStream(finalStoragePath + "/OK.txt");
//this returns immediatly with false result
boolean getResult=ftpClient.retrieveFile("OK.txt", os);
//this always fail for timeout
boolean result = ftpClient.storeFile( picture.getName(), buffIn );

我找不到这种特定情况的任何示例,所有示例都是关于正常的 FTP 连接,我可以毫无问题地实现。你们中有人遇到过类似的问题吗?我真的需要一个解决方案,我必须尽快交付项目。

谢谢。

【问题讨论】:

    标签: android ftp ftp-client apache-commons-net ftps


    【解决方案1】:

    我终于找到了解决方案,解决方案是将信任管理器设置为接受所有证书。这是遇到类似问题的人的代码,也许可以改进和/或优化它,但它可以工作:

    FTPSClient ftpClient = new FTPSClient("TLS", false);
    try {
        TrustManager[] trustManager = new TrustManager[] { new X509TrustManager() {
            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return null;
            }
    
            @Override
            public void checkClientTrusted(X509Certificate[] certs, String authType) {
            }
    
            @Override
            public void checkServerTrusted(X509Certificate[] certs, String authType) {
            }
        } };
    
        ftpClient.setTrustManager(trustManager[0]);
        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        kmf.init(null, null);
        KeyManager km = kmf.getKeyManagers()[0];
        ftpClient.setKeyManager(km);
        ftpClient.setBufferSize(1024 * 1024);
        ftpClient.setConnectTimeout(100000);
        ftpClient.connect(InetAddress.getByName("ipaddress"), 990);
        ftpClient.setSoTimeout(100000);
    
        if (ftpClient.login("user", "password")) {
            ftpClient.execPBSZ(0);
            ftpClient.execPROT("P");
            ftpClient.changeWorkingDirectory("/");
            // 250 = directory succesfully changed
            if (ftpClient.getReplyString().contains("250")) {
                ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
                ftpClient.enterLocalPassiveMode();
                BufferedInputStream buffIn = null;
    
                for (File picture : pictures) {
                    buffIn = new BufferedInputStream(new FileInputStream(picture.getAbsolutePath()));
                    boolean result = ftpClient.storeFile(picture.getName(), buffIn);
                    try {
                        buffIn.close();
                    } catch (Exception e) {
                    }
                    if (result)
                        picture.delete();
                }
            }
        }
    
    } catch (SocketException e) {
        Log.e("APPTAG", e.getStackTrace().toString());
    } catch (UnknownHostException e) {
        Log.e("APPTAG", e.getStackTrace().toString());
    } catch (IOException e) {
        Log.e("APPTAG", e.getStackTrace().toString());
    } catch (Exception e) {
        Log.e("APPTAG", e.getStackTrace().toString());
    } finally {
        try {
            ftpClient.logout();
        } catch (Exception e2) {
        }
        try {
            ftpClient.disconnect();
        } catch (Exception e2) {
        }
    }
    

    【讨论】:

    • 我尝试了您的解决方案,但是当它尝试上传文件时出现错误:I/System.out: javax.net.ssl.SSLException: Write error: ssl=0x7f9d8c6200: I/ O 系统调用时出错,Broken pipe
    【解决方案2】:

    您可以添加接受所有证书而不是创建一个的库信任管理器。

    FTPSClient mFtps = new FTPSClient();
    mFtps.setTrustManager(TrustManagerUtils.getAcceptAllTrustManager());
    

    【讨论】:

      【解决方案3】:

      getAcceptAllTrustManager() 表示不检查证书的有效性。如果您可以端到端控制所涉及的站点,则可能没问题。见:Trusting all certificates using HttpClient over HTTPS

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-07-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多