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

使用CSOM读取SharePoint站点页面并本地存储的问题求助

解决SharePoint站点页面本地存储的问题

我看你当前的代码有几个小问题导致拿不到页面内容,咱们一步步来修正:

1. 精准定位页面库

页面库的BaseTemplate是119没错,但你加载Lists的方式有点重复且不够精准。可以直接通过标题获取页面库(默认英文环境叫"Site Pages",中文环境通常是"站点页面"):

// 获取站点页面库
List pagesLibrary = web.Lists.GetByTitle("Site Pages");
clientcontext.Load(pagesLibrary);
clientcontext.ExecuteQuery();

2. 加载页面时必须指定内容字段

默认获取ListItem不会自动加载页面的核心内容字段,你需要明确指定要加载的字段——现代页面用CanvasContent1,经典发布页面用PublishingPageContent:

CamlQuery cq = CamlQuery.CreateAllItemsQuery();
ListItemCollection pageItems = pagesLibrary.GetItems(cq);
// 加载页面标题、内容、发布状态等关键字段
clientcontext.Load(pageItems, items => items.Include(
    item => item["Title"],
    item => item["CanvasContent1"], // 现代页面内容字段
    item => item["PublishingPageContent"], // 经典发布页面内容字段
    item => item["Level"] // 用于判断是否已发布
));
clientcontext.ExecuteQuery();

3. 筛选已发布/未发布页面

如果需要区分已发布(已批准)和未发布(草稿)页面,可以在CAML查询中添加过滤条件:

// 筛选已发布页面:Level字段值为2代表已发布,1代表草稿
string camlXml = @"
<View>
  <Query>
    <Where>
      <Eq>
        <FieldRef Name='Level' />
        <Value Type='Integer'>2</Value>
      </Eq>
    </Where>
  </Query>
</View>";
CamlQuery cq = new CamlQuery { ViewXml = camlXml };

4. 保存页面内容到本地

拿到页面内容后,就可以写入本地文件了,这里还做了重名处理避免覆盖:

// 创建本地存储目录
string localSaveDir = @"C:\LocalSharePointPages";
if (!Directory.Exists(localSaveDir))
{
    Directory.CreateDirectory(localSaveDir);
}

foreach (ListItem page in pageItems)
{
    string pageTitle = page["Title"].ToString();
    // 判断页面发布状态
    bool isPublished = page["Level"] != null && (int)page["Level"] == 2;
    string statusSuffix = isPublished ? "_已发布" : "_草稿";

    // 根据页面类型获取内容
    string pageContent = string.Empty;
    if (page.FieldValues.ContainsKey("CanvasContent1"))
    {
        pageContent = page["CanvasContent1"].ToString();
    }
    else if (page.FieldValues.ContainsKey("PublishingPageContent"))
    {
        pageContent = page["PublishingPageContent"].ToString();
    }

    // 处理重名文件
    string filePath = Path.Combine(localSaveDir, $"{pageTitle}{statusSuffix}.html");
    int counter = 1;
    while (File.Exists(filePath))
    {
        filePath = Path.Combine(localSaveDir, $"{pageTitle}{statusSuffix}_{counter}.html");
        counter++;
    }

    File.WriteAllText(filePath, pageContent);
    Console.WriteLine($"已保存:{filePath}");
}

完整修正后的代码示例

using Microsoft.SharePoint.Client;
using System.IO;
using System.Security;

class SharePointPageExporter
{
    static void Main(string[] args)
    {
        string siteUrl = "https://你的租户.sharepoint.com/sites/你的站点";
        string userId = "你的账号@租户.onmicrosoft.com";
        string password = "你的密码";

        SecureString securePass = new SecureString();
        foreach (char c in password)
        {
            securePass.AppendChar(c);
        }

        using (ClientContext clientContext = new ClientContext(siteUrl))
        {
            clientContext.Credentials = new SharePointOnlineCredentials(userId, securePass);
            Web web = clientContext.Web;
            clientContext.Load(web);
            clientContext.ExecuteQuery();

            // 获取站点页面库(中文环境改为"站点页面")
            List pagesLibrary = web.Lists.GetByTitle("Site Pages");
            clientContext.Load(pagesLibrary);
            clientContext.ExecuteQuery();

            // 查询所有页面并加载必要字段
            CamlQuery cq = CamlQuery.CreateAllItemsQuery();
            ListItemCollection pageItems = pagesLibrary.GetItems(cq);
            clientContext.Load(pageItems, items => items.Include(
                item => item["Title"],
                item => item["CanvasContent1"],
                item => item["PublishingPageContent"],
                item => item["Level"]
            ));
            clientContext.ExecuteQuery();

            // 本地存储目录
            string localDir = @"C:\LocalSharePointPages";
            if (!Directory.Exists(localDir))
            {
                Directory.CreateDirectory(localDir);
            }

            foreach (ListItem page in pageItems)
            {
                string pageTitle = page["Title"].ToString();
                bool isPublished = page["Level"] != null && (int)page["Level"] == 2;
                string statusSuffix = isPublished ? "_已发布" : "_草稿";

                string pageContent = string.Empty;
                if (page.FieldValues.ContainsKey("CanvasContent1"))
                {
                    pageContent = page["CanvasContent1"].ToString();
                }
                else if (page.FieldValues.ContainsKey("PublishingPageContent"))
                {
                    pageContent = page["PublishingPageContent"].ToString();
                }

                // 避免文件名重复
                string filePath = Path.Combine(localDir, $"{pageTitle}{statusSuffix}.html");
                int counter = 1;
                while (File.Exists(filePath))
                {
                    filePath = Path.Combine(localDir, $"{pageTitle}{statusSuffix}_{counter}.html");
                    counter++;
                }

                File.WriteAllText(filePath, pageContent);
                Console.WriteLine($"保存成功:{filePath}");
            }
        }
    }
}

几个额外注意点:

  • 确保你的账号有站点页面库的读取权限
  • 中文环境下记得把GetByTitle的参数改成"站点页面"
  • 现代页面和经典页面的内容字段不同,代码里已经做了兼容判断

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 03:07:39