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
相关产品推荐
相关产品推荐

