You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Delphi 10.3 Android环境下如何通过显式FTP TLS写入文件?

Delphi 10.3 Android平台FTP Put操作停滞问题解决

核心问题分析

你的代码在Android上出现停滞,主要源于以下几个关键问题:

  • UI线程阻塞:Android系统禁止在主线程(UI线程)执行网络IO操作,直接在按钮点击事件中调用FTP传输会触发应用无响应。
  • 路径与权限问题:硬编码的存储路径可能未获取正确文件访问权限,或路径解析逻辑错误。
  • 超时设置不合理:所有Timeout设为0会导致无限等待,一旦数据传输卡住就无法自行退出。

具体解决方案

1. 移至后台线程执行网络操作

使用Delphi的匿名线程将FTP操作移至后台,避免阻塞UI线程:

procedure TForm1.Button1Click(Sender: TObject);
begin
  TThread.CreateAnonymousThread(
    procedure
    var
      IdFTP: TIdFTP;
      IdSSLIO: TIdSSLIOHandlerSocketOpenSSL;
      LocalFilePath: string;
    begin
      IdFTP := TIdFTP.Create(nil);
      IdSSLIO := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
      try
        {$ifdef mswindows}
          IdOpenSSLSetLibPath('C:\Users\karol.campos\Desktop\FTPSExample\SSL');
        {$endif}
        {$ifdef android}
          IdOpenSSLSetLibPath(TPath.GetLibraryPath); // Android平台OpenSSL库默认存放路径
        {$endif}

        IdSSLIO.SSLOptions.Method := TIdSSLVersion.sslvSSLv23;
        IdSSLIO.PassThrough := true;
        IdFTP.IOHandler := IdSSLIO;
        IdFTP.ListenTimeout := 5000;   // 设置5秒连接超时
        IdFTP.ReadTimeout := 10000;    // 设置10秒读取超时
        IdFTP.TransferTimeout := 30000;// 设置30秒传输超时
        IdFTP.Passive := true;
        IdFTP.UseTLS := TIdUseTLS.utUseExplicitTLS;
        IdFTP.DataPortProtection := TIdFTPDataPortSecurity.ftpdpsPrivate;

        IdFTP.Host := '(ip_ftp)';
        IdFTP.Username := '(user)';
        IdFTP.Password := '(pass)';

        try
          IdFTP.Connect;
          try
            {$ifdef mswindows}
              LocalFilePath := 'D:\SeLogro.txt';
            {$endif}
            {$ifdef android}
              // 获取Android公共文档路径,需配置权限
              LocalFilePath := TPath.Combine(TPath.GetPublicDocumentsPath, 'SeLogro.txt');
            {$endif}

            if FileExists(LocalFilePath) then
            begin
              IdFTP.Put(LocalFilePath, 'SeLogro.txt', false);
              // 回到UI线程显示成功提示
              TThread.Synchronize(nil, procedure
              begin
                ShowMessage('Ready!');
              end);
            end
            else
            begin
              TThread.Synchronize(nil, procedure
              begin
                ShowMessage('本地文件不存在');
              end);
            end;
          finally
            IdFTP.Disconnect;
          end;
        except
          on E: Exception do
          begin
            TThread.Synchronize(nil, procedure
            begin
              ShowMessage('异常类: ' + E.ClassName + #13#10 + '错误信息: ' + E.Message);
            end);
          end;
        end;
      finally
        IdSSLIO.Free;
        IdFTP.Free;
      end;
    end).Start;
end;

2. 配置Android权限与路径

  • 在AndroidManifest.xml中添加文件读写权限:
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <!-- Android 10+ 需添加兼容配置 -->
    <application android:requestLegacyExternalStorage="true">
    </application>
    
  • 使用TPath类方法获取系统标准路径,避免硬编码,比如TPath.GetPublicDocumentsPath或TPath.GetExternalStoragePath。

3. 检查OpenSSL库部署

  • 将libssl.so和libcrypto.so放入项目对应架构目录(如libs\armeabi-v7a),确保IdOpenSSLSetLibPath指向正确的库路径(Android平台建议用TPath.GetLibraryPath)。

4. 调整超时设置

取消所有Timeout设为0的配置,设置合理的超时阈值(5-30秒),避免无限等待导致应用停滞。

内容的提问来源于stack exchange,提问作者Kenneth

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 23:55:19