文件属性字段如何扩展?

该组件仅适用于私有化WPS365版本

1. 方案概述

区分文件类别的信息就是文件属性,比如:.docx指文档,.xlsx指表格。

这里说的拓展文件属性指的是在文件属性后面打标签,方便后续查找和管理文件。

有哪些标签可以添加

企业可以根据自己的需求自行打标签,常用的标签有三类:

安全管控:比如标记“机密文件”,限制未经授权的人查看或编辑。

流程跟踪:比如标注“待审批”状态,提醒相关负责人处理。

协作管理:比如显示“可/不可分享”状态,避免文件外泄。

针对这种需求,我们可以使用文档中心Web端(PC端)的开放能力,定制文件属性扩展:

实现效果在.docx后,增添文件的更多属性,红色字体可根据企业需要,替换成企业的分类标签。3LAP4PY4AAQAM
支持端文档中心PC端
版本限制版本23-12b(含)以上
操作系统限制支持X86、XC

2. 使用指南

文件属性字段扩展

支持文件列表显示更多信息,如:分享状态.审批状态.安全标记等

👉能力

sdk.kdrive.myDocumentPage.fileList

👉代码示例

sdk.kdrive.myDocumentPage.fileList.onUpdate((data) => {
  const dataList = data.list.items()

  const fileList = sdk.kdrive.myDocumentPage.fileList
  const slotName = 'fileName'

  dataList.length &&
    dataList.forEach((item) => {
      const slot = fileList.fileItem(item['id'])[slotName]

      sdk.append(slot, <div style={{ color: 'red' }}>demo示例</div>, {
        key: 'test-tag',
      })
    })
})

👉效果截图

3LAP4PY4AAQAM

文件属性如何写到元数据

  • 第一步:注册实体扩展信息

post /config/dev/v1/reg_entity_extra

  • 第二步:修改文件元数据

post /v7/dev/drives/{drive_id}/files/{file_id}/update

  • 第三步:获取文件信息

get /v7/drives/{drive_id}/files/{file_id}/meta

👉效果截图

服务端

注册实体扩展信息

type Api struct {
    domain  string
    ak      string
    sk      string
    driveId string
    FileId  string
}

var (
    api        *Api
    apiSrvOnce sync.Once
)

func NewApiSrv() *Api {
    apiSrvOnce.Do(func() {
        api = &Api{
            domain:  "http://encs-pri-cams-engine",
            ak:      config.GlobalConfig.AK,
            sk:      config.GlobalConfig.Sk,
        }
    })
    return api
}

// 使用方自定义命名空间和name
var namespace, name string = "filetransfer", "transferTag"

// 注册实体信息扩展接口
func (a *Api) RegisterEntityExt() error {
    entityExtInfo := &EntityExtReq{
        Copyable:          true,
        EntityType:        "file",
        Movable:           true,
        Name:              name,
        Namespace:         namespace,
        RecycleRestorable: true,
        VersionRestorable: true,
    }

    h, _ := json.Marshal(entityExtInfo)

    uri := "/config/dev/v1/reg_entity_extra"
    // i接口,wps4签名
    wps4Header, err := wps4DocSign.Wps4DocsSign(a.ak, a.sk, uri, "POST", h)
    if err != nil {
        log.Error("wps4DocSign.Wps4DocsSign error: ", err)
        return fmt.Errorf("wps4DocSign.Wps4DocsSign error: %s", err)
    }

    // 发送请求
    url := fmt.Sprintf("%s/i/docmini%s", a.domain, uri)
    request, err := http.NewRequest("POST", url, bytes.NewReader(h))
    if err != nil {
        log.Error("http.NewRequest error: ", err)
        return fmt.Errorf("http.NewRequest error: %s", err)
    }

    request.Header.Set("Content-Type", wps4Header.ContentType)
    request.Header.Set("Wps-Docs-Date", wps4Header.Date)
    request.Header.Set("Wps-Docs-Authorization", wps4Header.Authorization)

    client := &http.Client{}

    resp, err := client.Do(request)
    if err != nil {
        log.Error("client.Do error: ", err)
        return fmt.Errorf("client.Do error: %s", err)
    }
    if resp != nil && resp.Body != nil {
        defer resp.Body.Close()
    }

    var respBody []byte

    if resp.StatusCode != http.StatusOK {
        if resp.Body != nil {
            respBody, _ = io.ReadAll(resp.Body)
            log.Error("RegisterEntityExt error: ", string(respBody), resp.StatusCode)
            return fmt.Errorf("RegisterEntityExt error: %s", string(respBody))
        } else {
            log.Error("RegisterEntityExt error: ", resp.StatusCode)
            return fmt.Errorf("RegisterEntityExt error: %d", resp.StatusCode)
        }
    }

    respBody, _ = io.ReadAll(resp.Body)

    respInfo := &BaseResp{}
    err = json.Unmarshal(respBody, respInfo)
    if err != nil {
        log.Error("json.Unmarshal error: ", err)
        return fmt.Errorf("json.Unmarshal error: %s", err)
    }
    log.Info("RegisterEntityExt success: ", respInfo)
    return nil
}

修改文件元数据

// 修改文件元数据接口
func (a *Api) ModifyFileMeta(driveId, fileId string) error {
    fileMetaReq := &ModifyFileMetaReq{
        ExtAttr: ExtAttr{
            Name:  name,
            Value: "test",
        },
    }

    h, _ := json.Marshal(fileMetaReq)
    uri := fmt.Sprintf("/v7/dev/drives/%s/files/%s/update", driveId, fileId)
    // i接口,wps4签名
    wps4Header, err := wps4DocSign.Wps4DocsSign(a.ak, a.sk, uri, "POST", h)
    if err != nil {
        log.Error("wps4DocSign.Wps4DocsSign error: ", err)
        return fmt.Errorf("wps4DocSign.Wps4DocsSign error: %s", err)
    }

    // 发送请求
    url := fmt.Sprintf("%s/i/docmini%s", a.domain, uri)
    request, err := http.NewRequest("POST", url, bytes.NewReader(h))
    if err != nil {
        log.Error("http.NewRequest error: ", err)
        return fmt.Errorf("http.NewRequest error: %s", err)
    }

    request.Header.Set("Content-Type", wps4Header.ContentType)
    request.Header.Set("Wps-Docs-Date", wps4Header.Date)
    request.Header.Set("Wps-Docs-Authorization", wps4Header.Authorization)

    client := &http.Client{}

    resp, err := client.Do(request)
    if err != nil {
        log.Error("client.Do error: ", err)
        return fmt.Errorf("client.Do error: %s", err)
    }

    if resp != nil && resp.Body != nil {
        defer resp.Body.Close()
    }

    var respBody []byte

    if resp.StatusCode != http.StatusOK {
        if resp.Body != nil {
            respBody, _ = io.ReadAll(resp.Body)
            log.Error("ModifyFileMeta error: ", string(respBody), resp.StatusCode)
            return fmt.Errorf("ModifyFileMeta error: %s", string(respBody))
        } else {
            log.Error("ModifyFileMeta error: ", resp.StatusCode)
            return fmt.Errorf("ModifyFileMeta error: %d", resp.StatusCode)
        }
    }

    respBody, _ = io.ReadAll(resp.Body)

    respInfo := &BaseResp{}

    err = json.Unmarshal(respBody, respInfo)
    if err != nil {
        log.Error("json.Unmarshal error: ", err)
        return fmt.Errorf("json.Unmarshal error: %s", err)
    }

    log.Info("ModifyFileMeta success: ", respInfo)
    return nil
}

获取文件信息

// 获取文件信息接口
func (a *Api) GetFileInfo(driveId, fileId string) (*FileInfoResp, error) {
    uri := fmt.Sprintf("/open/v7/drives/%s/files/%s/meta?with_permission=true&with_ext_attrs=true", driveId, fileId)
    wps4Header, err := wps4DocSign.Wps4DocsSign(a.ak, a.sk, uri, "GET", nil)
    if err != nil {
        log.Error("wps4DocSign.Wps4DocsSign error: ", err)
        return nil, fmt.Errorf("wps4DocSign.Wps4DocsSign error: %s", err)
    }

    // 发送请求
    url := fmt.Sprintf("%s/i/docmini%s", a.domain, uri)
    request, err := http.NewRequest("GET", url, nil)
    if err != nil {
        log.Error("http.NewRequest error: ", err)
        return nil, fmt.Errorf("http.NewRequest error: %s", err)
    }

    request.Header.Set("Content-Type", wps4Header.ContentType)
    request.Header.Set("Wps-Docs-Date", wps4Header.Date)
    request.Header.Set("Wps-Docs-Authorization", wps4Header.Authorization)

    client := &http.Client{
        Transport: &http.Transport{
            TLSClientConfig: &tls.Config{
                InsecureSkipVerify: true,
            },
        },
    }

    resp, err := client.Do(request)

    if err != nil {
        log.Error("client.Do error: ", err)
        return nil, fmt.Errorf("client.Do error: %s", err)
    }

    if resp != nil && resp.Body != nil {
        defer resp.Body.Close()
    }

    var respBody []byte

    if resp.StatusCode != http.StatusOK {
        if resp.Body != nil {
            respBody, _ = io.ReadAll(resp.Body)
            log.Error("GetFileInfo error: ", string(respBody), resp.StatusCode)
            return nil, fmt.Errorf("GetFileInfo error: %s", string(respBody))
        } else {
            log.Error("GetFileInfo error: ", resp.StatusCode)
            return nil, fmt.Errorf("GetFileInfo error: %d", resp.StatusCode)
        }
    }

    respBody, _ = io.ReadAll(resp.Body)

    log.Info("GetFileInfo success: ", string(respBody))

    fileInfoResp := &FileInfoResp{}

    err = json.Unmarshal(respBody, fileInfoResp)

    if err != nil {
        log.Error("json.Unmarshal error: ", err)
        return nil, fmt.Errorf("json.Unmarshal error: %s", err)
    }

    return fileInfoResp, nil
}

结果

DX5ZWAY5AAAGO

前端

sdk.kdrive.myDocumentPage.fileList.onUpdate(async data => {
  let tag = "transferTag"
  let isRenderTag: boolean = false  // 保证满足条件再进行tag渲染
  let driveId = '4'
  let fileId = '286034168381441'
  try {
    let { data: fileInfo } = await request.get(
      `/cloud/file/u/v1/drives/${driveId}/files/${fileId}`
    )
    console.log('ecis: index start2', fileInfo)

    const extraAttrs = JSON.parse(fileInfo.data.extra)
    if (extraAttrs && extraAttrs[tag]) {
      isRenderTag = true
    }
  } catch (error) {
    console.error('render tag error:', error)
  }

  const dataList = data.list.items()
  const fileList = sdk.kdrive.myDocumentPage.fileList
  const slotName = 'fileName'

  dataList.length && isRenderTag &&
    dataList.forEach(item => {
      const slot = fileList.fileItem(item['id'])[slotName]
      sdk.append(slot, <div style={{ color: 'red' }}>{extraAttrs[tag]}</div>, {
        key: tag
      })
    })
})

结果

HMRGAEQ5ADAE6

相关新闻

  • AI在组织级“水土不服”?轻舟AI解法来了

    AI在组织级“水土不服”?轻舟AI解法来了

    WPS 365 轻舟AI,专为组织级打造的私有化轻量AI办公方案。

    最佳实践 2026年5月8日
  • 限制用户下载特定文件

    限制用户下载特定文件

    在员工离职或出于其它安全考虑,企业需要对员工创建或管理的文件进行管控,或对扫描出敏感信息的文件进行管控,限制文件下载。 如何限制企业用户下载特定文件 本定制方案仅适用于私有化WPS365版本 1. 方案概述 员工离职前,出于安全考虑,企业会对其创建或管理的文件进行管控。 管控会有两个实现方式: 有安全管控需求时,比如文件扫描出敏感信息,用户的网络环境(内网或外网)、文件大小不满足管理规定,都有可能需要限制下载。 针对这两种情况,我们可以使用文档中心Web端(PC端)的开放能力,定制下载功能: 实…

    最佳实践 2025年12月11日
  • 【最佳实践】通过WPS 365快速构建企业级AI知识库

    【最佳实践】通过WPS 365快速构建企业级AI知识库

    在企业知识库中,您可以更加集中关注企业沉淀的知识文件夹,在其中可以通过快速阅读、问答等功能,快速获取知识、解答疑问,大幅提升办公效率。

    最佳实践 2026年1月1日
  • 自定义文件列表右键菜单项

    自定义文件列表右键菜单项

    企业需要在文件列表的右键菜单栏中,新增其它定制菜单项 如何在文件列表新增右键菜单项? 本定制方案仅适用于私有化WPS365版本 1. 方案概述 有时候,企业需要给不在组织通讯录中的成员共享文档,传统流程是把文档下载下来,通过邮件发送,易导致效率瓶颈。 现在,通过文档中心的扩展能力,可以直接在文件列表右键菜单新增自定义分享弹窗入口,简化协作流程。 这一功能不仅支持自定义分享弹窗,企业也可根据实际需要,在文件列表的右键菜单栏中,新增其它定制菜单项。 我们可以使用文档中心Web端(PC端)的开放能力,…

    最佳实践 2025年12月11日
  • 文档中心欢迎页定制

    文档中心欢迎页定制

    在文档中心登录前进行品牌展示,为满足企业或组织的的个性化需求 如何为文档中心定制欢迎页? 该组件仅适用于私有化WPS365版本 1. 方案概述 欢迎页是由客户自己设计和定义的独立页面,可以在文档中心登录前进行品牌展示。 总的来说,欢迎页的内容客户可以根据自己的需求自行设计,通常比较高频的使用方式有: 如果没有定制欢迎页,客户在登录文档中心时,会直接进入文档中心登录页,输入账号和密码进行登录。 客户定制了文档中心欢迎页之后,遇到需要登录的场景,会先跳转进入企业欢迎页,在欢迎页进行相关操作(例如:点…

    最佳实践 2025年12月11日
  • WPS协作产品消息审计能力助力客户应对信息安全、合规及消息追溯的挑战

    WPS协作产品消息审计能力助力客户应对信息安全、合规及消息追溯的挑战

    为了满足数字化办公时代组织对于企业内风险消息监控的需求,WPS提供了审计授权、消息搜索、审计操作、审计设置及审计日志等几大能力,助力企业提升内部消息的安全性和合规性。 能力简介 在数字化办公时代,即时通讯(IM)工具在组织的作用越发重要,随之要面对的就是风险消息监控、敏感词过滤、日志全量留存及多维分析等诸多问题来确保企业通讯的合规性。WPS协作产品为客户提供了消息审计的相关接口和基础能力,基于相关接口和能力,客户可以通过开发实现内容识别拦截违规信息、完整记录消息内容、时间、参与方等元数据,支持分…

    最佳实践 2025年12月11日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

立即咨询 企业版试用 上门服务

请您留言

感谢您的关注,你可留下联系方式,我们将第一时间与您联系。