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

使用CSOM操作SPO列表(强制签出)报错:文件被独占锁定

问题:SharePoint Online强制签出列表中修改文件ContentType时提示“文件被独占锁定”

我开发了一款Word Add-In,功能是把Word文档导出成PDF后上传到SharePoint Online(SPO)列表,同时给新上传的PDF分配ContentType和SPO元数据。目标列表的配置如下:

  • 启用主次版本控制
  • 开启强制文件签出要求

导出和上传操作都能正常执行,但当Add-In尝试给文件分配新ContentType时,SPO抛出异常:file is locked for exclusive use by [当前执行Add-In的用户]。要是列表没开强制签出,这个功能就能正常运行。

现有代码

public void FileAssignContentType(string relativeFullName, string listTitle, string contentTypeName)
{
    try
    {
        // connect to list
        Microsoft.SharePoint.Client.List list = this.web.GetListByUrl(listTitle);
        this.clientContext.Load(list);
        this.clientContext.ExecuteQuery();

        // get content type
        ContentType newCT = list.GetContentTypeByName(contentTypeName);
        this.clientContext.Load(newCT, x => x.Id);
        this.clientContext.ExecuteQuery();

        // assign content type to file
        Microsoft.SharePoint.Client.File file = this.getFile(relativeFullName);
        this.clientContext.ExecuteQuery();

        ListItem item = list.GetItemByUniqueId(file.UniqueId);
        this.clientContext.Load(item);
        this.clientContext.ExecuteQuery();

        item["ContentTypeId"] = newCT.Id;
        item.Update();
        this.clientContext.ExecuteQuery(); // -> raises exception
    }
    catch (Exception ex)
    {
        throw new Exception(ex.Message);
    }
}

原因分析

因为列表开启了强制签出,文件上传后会自动处于签出状态(当前用户就是签出者),此时直接修改ListItem会触发SPO的锁定检测,导致抛出“文件被独占锁定”的异常。

解决方案

在修改ContentType之前,先检查文件的签出状态,把文件签入后再进行更新操作。如果业务需要文件保持签出,更新完成后可以重新签出。

修改后的代码示例:

public void FileAssignContentType(string relativeFullName, string listTitle, string contentTypeName)
{
    try
    {
        // 连接目标列表
        Microsoft.SharePoint.Client.List list = this.web.GetListByUrl(listTitle);
        this.clientContext.Load(list);
        this.clientContext.ExecuteQuery();

        // 获取要分配的ContentType
        ContentType newCT = list.GetContentTypeByName(contentTypeName);
        this.clientContext.Load(newCT, x => x.Id);
        this.clientContext.ExecuteQuery();

        // 获取文件并加载签出状态、唯一ID
        Microsoft.SharePoint.Client.File file = this.getFile(relativeFullName);
        this.clientContext.Load(file, f => f.CheckOutType, f => f.UniqueId);
        this.clientContext.ExecuteQuery();

        // 若文件处于签出状态,先签入
        if (file.CheckOutType != CheckOutType.None)
        {
            // 按版本策略选择签入类型:MajorCheckIn生成主版本,MinorCheckIn生成次版本
            file.CheckIn("签入以更新ContentType", CheckinType.MajorCheckIn);
            this.clientContext.ExecuteQuery();
        }

        // 更新文件的ContentType
        ListItem item = list.GetItemByUniqueId(file.UniqueId);
        this.clientContext.Load(item);
        this.clientContext.ExecuteQuery();

        item["ContentTypeId"] = newCT.Id;
        item.Update();
        this.clientContext.ExecuteQuery();

        // 可选:如果需要保持文件签出状态,更新后重新签出
        // file.CheckOut();
        // this.clientContext.ExecuteQuery();
    }
    catch (Exception ex)
    {
        throw new Exception(ex.Message);
    }
}

补充说明

  • 签入类型CheckinType的选择:如果列表启用主次版本,MajorCheckIn会生成1.0、2.0这类主版本,MinorCheckIn生成1.1、1.2这类次版本,根据你的业务需求选择即可。
  • 确保操作的用户拥有签入/签出权限,以及修改列表项的权限。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 21:47:13