从文档库的所有子文件夹检索所有文档 - CSOM

9
我正在使用客户端对象模型(C#)来检索包含子文件夹的文档库中的所有列表项。我查阅了MSDN文档,但卡在了为什么无法获取字段属性上,或者我是否做对了这件事情。
    NetworkCredential credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
            ClientContext clientcontext = new ClientContext(Resources.defaultSPSite);
            clientcontext.Credentials = credentials;

            //Load Libraries from SharePoint
            //Web site = clientcontext.Web;
            clientcontext.Load(clientcontext.Web.Lists);
            clientcontext.ExecuteQuery();


            //List sharedDocumentsList = clientcontext.Web.Lists.GetByTitle("TestLDOCS");
            //CamlQuery camlQuery = new CamlQuery();
            //camlQuery.ViewXml = @"<View Scope='Recursive'><Query></Query></View>";

            foreach (List list in clientcontext.Web.Lists)
            {
                clientcontext.Load(list);
                clientcontext.ExecuteQuery();
                //list.TemplateFeatureId.ToString().Equals("") &&
                    string baseType =  list.BaseType.ToString();
                    string listTitle = list.Title.ToString();
                    if (list.BaseType.ToString().Equals("DocumentLibrary", StringComparison.InvariantCultureIgnoreCase) && list.Title.ToString().Equals("TestLDOCS", StringComparison.InvariantCultureIgnoreCase))
                    {
                        foreach (Folder subFolder in list.RootFolder.Folders)
                        {
                            foreach (File f in subFolder.Files)
                            {
                                Console.WriteLine((string) f.Title);                     
                            }
                        }
                    }
             }
        }

我收到的错误是“foreach (File f in subFolder.Files)”集合可能没有初始化的错误。有没有办法使用CSOM获取文档库中每个子文件夹中所有文档的字段值?
我知道您也可以使用列表项强类型化字段值,例如(listItem ["fieldName"]). 那么我应该选择这条路吗?
2个回答

14

一些建议:

1)推荐使用ClientRuntimeContext.LoadQuery方法来加载特定的列表,例如:

var lists = ctx.LoadQuery(ctx.Web.Lists.Where(l => l.BaseType == BaseType.DocumentLibrary));
ctx.ExecuteQuery();

2) 由于SharePoint SCOM支持请求批处理,建议最小化对服务器的请求次数。以下示例演示如何执行单个请求以从文档库加载所有文件:

foreach (var list in lists)
{
    var items = list.GetItems(CreateAllFilesQuery());
    ctx.Load(items, icol => icol.Include(i => i.File));
    results[list.Title] = items.Select( i=>i.File);
}
ctx.ExecuteQuery();

3) 更倾向于通过下面演示的 CAML 查询方式加载所有文件:

public static CamlQuery CreateAllFilesQuery()
{
   var qry = new CamlQuery();
   qry.ViewXml ="<View Scope=\"RecursiveAll\"><Query><Where><Eq><FieldRef Name=\"FSObjType\" /><Value Type=\"Integer\">0</Value></Eq></Where></Query></View>";
   return qry;
}

接下来的示例将返回库中的所有文件:

var items = list.GetItems(CreateAllFilesQuery());
ctx.Load(items, icol => icol.Include(i => i.File));
ctx.ExecuteQuery();
var files = items.Select( i=>i.File).ToList();

从性能角度来看,这是一种更优化的加载特定列表的方式。

完整示例

如何使用SharePoint CSOM从文档库加载所有文件:

using (var ctx = new ClientContext(webUri))
{

     var results = new Dictionary<string, IEnumerable<File>>();
     var lists = ctx.LoadQuery(ctx.Web.Lists.Where(l => l.BaseType == BaseType.DocumentLibrary));
     ctx.ExecuteQuery();
     foreach (var list in lists)
     {
         var items = list.GetItems(CreateAllFilesQuery());
         ctx.Load(items, icol => icol.Include(i => i.File));
         results[list.Title] = items.Select( i=>i.File);
     }
     ctx.ExecuteQuery();

     //Print results
     foreach (var result in results)
     {
         Console.WriteLine("List: {0}",result.Key);
         foreach (var file in result.Value)
         {
             Console.WriteLine("File: {0}", file.Name);
         }
      }        
}

你的方法看起来非常好,但是我在 items.Select(i => i.File) 上遇到了 NotSupportedException。 - Santhos

2
foreach (List list in clientcontext.Web.Lists)
        {
            clientcontext.Load(list);
            clientcontext.ExecuteQuery();
            //list.TemplateFeatureId.ToString().Equals("") &&
                string baseType =  list.BaseType.ToString();
                string listTitle = list.Title.ToString();
                if (list.BaseType.ToString().Equals("DocumentLibrary", StringComparison.InvariantCultureIgnoreCase) && list.Title.ToString().Equals("TestLDOCS", StringComparison.InvariantCultureIgnoreCase))
                {
                    foreach (Folder subFolder in list.RootFolder.Folders)
                    {
           clientcontext.Load(subFolder.Files);
                   clientcontext.ExecuteQuery();
                        foreach (File f in subFolder.Files)
                        {
                            Console.WriteLine((string) f.Title);                     
                        }
                    }
                }
         }
    }

你缺少了针对"list.RootFolder"和"list.RootFolder.Folders"的额外查询负载。如果你不添加它们,这个功能将无法正常工作(会出现初始化错误)。但是感谢你让我更接近目标。 :) - Stephen McCormick

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接