为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

繁花不似锦 2021-08-19 17:50:10
我正在尝试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 环回)连接到它。我怎样才能解决这个问题?
查看完整描述

1 回答

?
慕姐8265434

TA贡献1813条经验 获得超2个赞

虽然我不熟悉 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();

    }

}


查看完整回答
反对 回复 2021-08-19
  • 1 回答
  • 0 关注
  • 199 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信