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

求助:使用Dropbox API无法获取完整目录文件列表的问题

问题描述

我开发了两个应用:一个负责将数据压缩包上传至对应公司的指定文件夹,运行正常;另一个用于将这些压缩包拉取到客户站点做本地备份,在文件数量达到约700个后出现问题。我通过调用Dropbox API请求指定目录下的压缩文件列表,解析文件名中的创建时间以获取最新文件,但API未返回完整列表,导致无法获取正确的文件。

原代码如下:

private static string GetFileFromDropbox()
{

  try
  {
    var client = CreateDropBoxInstance();
    var pathtofiles = $"/{Settings.Default.CompanyCode}";

    //var list = await client.Files.ListFolderGetLatestCursorAsync(pathtofiles);
    
    // changed 11/9/22 by Eric since it was not returning all files
    //var list = client.Files.ListFolderAsync(pathtofiles);
    var list = client.Files.ListFolderAsync(pathtofiles, true, true, false);
    
    var newlist = new List<string>();

    foreach (var l in list.Result.Entries)
    {
      if (!l.IsFile) continue;
      newlist.Add(l.PathLower.Replace($"/{Settings.Default.CompanyCode.ToLower()}/", string.Empty));
    }

    var dict = new Dictionary<DateTime, string>();
    foreach (var fn in newlist)
    {
      // filename: AAB.20211126234249.zip
      var parse = fn.Split('.');
      if (parse.Length != 3) continue;

      var date = parse[1];
      // cc yy mm dd hh mm   ss
      // 20 21 11 26 23 42   49
      // 01 23 45 67 89 1011 1213

      if (date.Length != 14) continue;

      var cc = int.Parse(date.Substring(0, 2));
      var yy = int.Parse(date.Substring(2, 2));
      var mm = int.Parse(date.Substring(4, 2));
      var dd = int.Parse(date.Substring(6, 2));
      var hh = int.Parse(date.Substring(8, 2));
      var mi = int.Parse(date.Substring(10, 2));
      var ss = int.Parse(date.Substring(12, 2));
      var filedate = new DateTime(cc + yy, mm, dd, hh, mi, ss);
      dict.Add(filedate, fn);

    }

    var qry = (from x in dict
               orderby x.Key descending
               select x.Value).FirstOrDefault();
    return qry;
  }
  catch (Exception e)
  {
    Console.WriteLine(e);
    throw;
  }
}
解决方案

Dropbox API的ListFolderAsync会分页返回结果,当存在未返回的剩余文件时,返回结果的HasMore属性为true,同时会提供Cursor参数,需要通过ListFolderContinueAsync循环获取所有分页数据,直到HasMore为false。

另外原代码还存在两个关键问题:

  1. 同步调用异步方法(list.Result)易引发死锁,建议改为异步方法。
  2. 日期解析逻辑错误:cc + yy会将年份计算为41(比如20+21),正确应为cc*100 + yy得到完整年份(如2021)。
  3. Dictionary<DateTime, string>存在重复键风险,若两个文件时间戳完全相同,dict.Add会抛出异常,建议改用列表存储后排序。
修改后的代码
private static async Task<string> GetFileFromDropboxAsync()
{
    try
    {
        var client = CreateDropBoxInstance();
        var pathtofiles = $"/{Settings.Default.CompanyCode}";
        var newlist = new List<string>();

        // 首次调用获取初始文件列表
        var listResult = await client.Files.ListFolderAsync(pathtofiles, true, true, false);
        AddFilesToList(listResult.Entries, newlist);

        // 循环获取剩余分页数据
        while (listResult.HasMore)
        {
            listResult = await client.Files.ListFolderContinueAsync(listResult.Cursor);
            AddFilesToList(listResult.Entries, newlist);
        }

        // 存储文件时间与文件名,避免重复键问题
        var fileInfos = new List<(DateTime FileDate, string FileName)>();
        foreach (var fn in newlist)
        {
            // filename: AAB.20211126234249.zip
            var parse = fn.Split('.');
            if (parse.Length != 3) continue;

            var dateStr = parse[1];
            if (dateStr.Length != 14) continue;

            // 正确解析完整年份
            var year = int.Parse(dateStr.Substring(0, 4));
            var month = int.Parse(dateStr.Substring(4, 2));
            var day = int.Parse(dateStr.Substring(6, 2));
            var hour = int.Parse(dateStr.Substring(8, 2));
            var minute = int.Parse(dateStr.Substring(10, 2));
            var second = int.Parse(dateStr.Substring(12, 2));
            
            var filedate = new DateTime(year, month, day, hour, minute, second);
            fileInfos.Add((filedate, fn));
        }

        // 按时间倒序获取最新文件
        return fileInfos.OrderByDescending(x => x.FileDate).Select(x => x.FileName).FirstOrDefault();
    }
    catch (Exception e)
    {
        Console.WriteLine(e);
        throw;
    }
}

// 提取重复逻辑,提升代码复用性
private static void AddFilesToList(IEnumerable<Metadata> entries, List<string> fileList)
{
    foreach (var entry in entries)
    {
        if (entry.IsFile)
        {
            var fileName = entry.PathLower.Replace($"/{Settings.Default.CompanyCode.ToLower()}/", string.Empty);
            fileList.Add(fileName);
        }
    }
}
关键修改点说明
  • 将方法改为异步Task<string>类型,使用await调用API,避免同步阻塞与死锁。
  • 新增分页循环:通过HasMore判断是否有剩余数据,结合Cursor调用ListFolderContinueAsync获取全部文件。
  • 修正日期解析逻辑:直接截取前4位作为完整年份,避免原代码的计算错误。
  • 改用List<(DateTime, string)>存储文件信息,规避Dictionary的重复键异常。
  • 提取AddFilesToList方法,减少代码冗余,提升可读性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 02:10:33