在 Android 模拟器中从本地 FTP 服务器下载时出现错误

我正在尝试FTPSClient使用在 Android 模拟器中运行的Java 从本地 FileZilla 服务器下载文件。


我写了这个帮助代码来下载一个文件:


public boolean downloadSingleFile(FTPSClient ftpClient,

                                  String remoteFilePath, File downloadFile) {

    OutputStream outputStream;

    Log.i("t1", remoteFilePath + " - " + downloadFile.getAbsolutePath());

    try {

        outputStream = new BufferedOutputStream(new FileOutputStream(

                downloadFile));

        ftpClient.setFileType(FTP.BINARY_FILE_TYPE);

        boolean retval = ftpClient.retrieveFile(remoteFilePath, outputStream);

        outputStream.flush();

        return retval;

    } catch (Exception e) {

        Log.e("dwFile", e.toString());

        Log.e("dwFile", ftpClient.getReplyString());

    } return false;

}

我这样称呼这个函数:


FTPSClient dwClient = new FTPSClient();

dwClient.addProtocolCommandListener(

    new PrintCommandListener(

    new PrintWriter(new OutputStreamWriter(System.out, "UTF-8")), true));

dwClient.setConnectTimeout(30 * 1000);

dwClient.connect(OmsSettingsFunctions.getFTPServer());

Log.i("dwDB", dwClient.getReplyString());

if (dwClient.login(FPTuser, FTPpass))  {

    Log.i("dwDB", dwClient.getReplyString());

    dwClient.enterLocalPassiveMode();

    File dwFile = new File(externalPath + "/Android/data/com.myapp/files/Documents/db.temp");

    if(!downloadSingleFile(dwClient, "/DBs/db.txt", dwFile)) {

        Log.e("dwDB", "Download could not finish (DB)");

        Log.e("dwDB", dwClient.getReplyString());

    }...


我已经尝试使用enterLocalActivemode()而不是,enterLocalPassivmode()但它没有帮助。FTP 服务器在我的本地机器上执行和运行 TLS。我通过 10.0.2.2(Android 环回)连接到它。我怎样才能解决这个问题?


繁花不似锦
浏览 228回答 1
1回答

慕姐8265434

虽然我不熟悉 Android Emulator,但我假设您需要连接到 10.0.2.2 才能连接到模拟器主机。在 FTP 被动模式下,服务器发回一个 IP 地址,FTP 客户端需要连接到该地址来传输文件(或目录列表)。当您的 FTP 服务器侦听 127.0.0.1 时,它会发回该 IP 地址。但是 127.0.0.1 指的是(模拟的)Android 主机,在您的 Android 代码上下文中。因此,“连接被拒绝”。这与连接到 NAT 后的 FTP 服务器的常见问题非常相似。请参阅通过 NAT 在端口 2000 上运行的 FTP 服务器无法在被动模式下工作因此解决方案是相同的:在 FileZilla 服务器界面中,转到编辑 > 设置 > 被动模式设置 > IPv4 特定 > 被动模式传输的外部服务器 IP 地址。并输入 10.0.2.2。也许您还需要取消选中“不要将外部 IP 用于本地连接”。显然,这反过来又使普通客户端无法使用 FTP 服务器。并且您已正确评论,此问题仅在从 Android 模拟器连接到在模拟器主机上运行的 FTP 服务器时出现。另一种解决方案是使用FTPClient.setPassiveNatWorkaroundStrategy. 它接受HostnameResolver接口的实现。如果您以将 127.0.0.1 转换为 10.0.2.2 的方式实现,即使服务器上没有任何更改,它也将允许您的 Java 代码连接。public static class ServerResolverImpl implements HostnameResolver {    private FTPClient client;    public ServerResolverImpl(FTPClient client) {        this.client = client;    }    @Override    public String resolve(String hostname) throws UnknownHostException {        return this.client.getRemoteAddress().getHostAddress();    }}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java