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

Android平台使用Indy TIdFTP组件FTP文件下载不完整问题排查

FTP文件夹下载在Android平台不稳定的问题

我实现了一段用于下载FTP服务器中文件夹及子文件夹内文件的代码,在Windows平台运行完全正常,但在Android平台上,虽能正常遍历所有文件夹及子文件夹,却出现文件有时全部下载、有时仅部分下载、有时完全不下载的情况。请问可能是什么原因导致的?

代码实现

void TFAct::Download()
{
  try
  {
    Ftp->ChangeDir("/");
    //Actualizo//
    NewDats(CTemp);
  }
  catch (...)
  {
  }
}

void TFAct::NewDats(AnsiString Path)
{
  std::auto_ptr<TStringList> Elementos (new TStringList);
  Ftp->List(Elementos.get());
  int NumElemnt = Ftp->DirectoryListing->Count;
  int Pos;
  bool *IsDir = new  bool[NumElemnt];
    
  for (int i=0;i<NumElemnt;i++)
  {
    TIdFTPListItem*  ListItem = Ftp->DirectoryListing->Items[i];
    Elementos->Strings[i] = ListItem->FileName;
    FechAlla[i] = ListItem->ModifiedDate;
    IsDir[i]=ListItem->ItemType == ditDirectory;
  }
    
  for (int i=0;i<NumElemnt;i++)
  {
    //Si es una SubCarpeta
    if(IsDir[i])
    {
      Ruta = Path + Elementos->Strings[i];
      AnsiString Copia = Path + Elementos->Strings[i];
      Folder = Ruta.SubString(Ruta.LastDelimiter("\\")+1,Ruta.Length());
    
      //Compruebo si el Directorio existe
      if(DirectoryExists(Ruta))
      {
        Ftp->ChangeDir(Elementos->Strings[i]);
        NewDats(Ruta + "/");
      }
      else
      {
        CreateDir(Ruta);
        Ftp->ChangeDir(Elementos->Strings[i]);
        NewDats(Ruta + "/");
      }
    }
    else
    {
      try
      {
        Ftp->Get(Elementos->Strings[i],Copia,true); //bajo archivo
      }
      catch(...)
      {
      }
    } //IsDir
    
  }//for
    
  Ftp->ChangeDirUp();
}

可能的原因分析

1. 存储权限限制

Android对文件系统访问有严格的权限管控:

  • Android 6.0(API 23)及以上需要动态申请WRITE_EXTERNAL_STORAGE权限;
  • Android 11(API 30)及以上需要申请MANAGE_EXTERNAL_STORAGE权限才能访问公共存储区。
    如果权限未正确授予,文件写入会静默失败,导致部分或全部文件下载无结果。

2. 路径分隔符不兼容

代码中混合使用Windows风格的\和Unix风格的/作为路径分隔符。Android系统默认使用/,使用\可能导致本地路径解析错误,文件无法写入到正确位置,看起来像是下载失败。

3. 网络超时与重试缺失

Android设备的网络环境波动更大,而代码未设置FTP操作的超时参数(如ConnectTimeout、ReadTimeout)。一旦网络短暂中断,TIdFTP::Get会直接失败,且没有重试逻辑,导致文件下载中断。

4. 异常吞吃掩盖问题

代码中大量使用catch (...)吞吃所有异常,没有任何错误日志输出。Android平台上,磁盘空间不足、FTP服务器权限拒绝、文件名编码不兼容等问题都会抛出异常,但被吞吃后无法定位具体故障点。

5. UI线程阻塞被系统终止

如果下载操作在UI线程中执行,Android系统会因为UI线程长时间阻塞(超过5秒)触发ANR(应用无响应),甚至强制终止下载进程,导致文件下载不完全。

6. 文件名编码不匹配

FTP服务器的文件名可能使用非UTF-8编码(如GBK),而Android默认使用UTF-8解析文件名,导致文件名解析错误,无法正确请求FTP文件或创建本地文件。

修复建议

  • 权限处理:在AndroidManifest.xml中声明存储权限,并在运行时动态申请;针对Android 11+,引导用户授予MANAGE_EXTERNAL_STORAGE权限。
  • 统一路径分隔符:将所有路径操作改为使用/,例如把LastDelimiter("\\")改为LastDelimiter("/")。
  • 添加超时与重试:设置Ftp->ConnectTimeout = 5000、Ftp->ReadTimeout = 10000等超时参数,并在Get失败时添加重试逻辑(最多3次)。
  • 移除异常吞吃:捕获具体异常类型(如EIdFTPException、EFOpenError),并通过Android Logcat输出错误信息,便于排查问题。
  • 后台线程执行:将下载操作放到后台线程(如TThread或Android原生异步任务)中执行,避免阻塞UI线程。
  • 统一文件名编码:设置Ftp->ControlEncoding = "UTF-8"(或匹配服务器的编码),确保文件名解析一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 08:47:44