类型化元数据值与附件
business object 的元数据属性(GET/PATCH /v1/twin/{contextId}/object/{objectId}/metadata 中的 metadata)不限于简单的 string、number 和 boolean。属性值也可以是携带特殊字段 _p3d_type 的标记对象,用于表示外部链接或已上传的文件附件。本页介绍该值联合类型,以及 attachment 类型背后的上传流程。
元数据值联合类型
Section titled “元数据值联合类型”元数据分区中的每个属性都是以下之一:
| 值类型 | 形式 |
|---|---|
| 简单 string | "A short text" |
| 简单 number | 42 |
| 简单 boolean | true |
| External link | { "url": "...", "text": "...", "_p3d_type": "urn:primitive:obj:external-link" } |
| Attachment | { "name": "...", "id": "...", "_p3d_type": "urn:primitive:obj:attachment" } |
_p3d_type 是判别字段:它的字面值告诉你正在查看哪一种标记形式。除此之外,两种标记形式都是普通对象;读取它们不需要额外的接口,只要返回元数据的地方,它们就会内联返回。
{ "Section name": { "name": "A short text", "numeric value": 42, "toggle name": true, "documentation link": { "url": "https://doc.prevu3d.com/", "text": "https://doc.prevu3d.com/", "_p3d_type": "urn:primitive:obj:external-link" }, "landing image": { "name": "prevu_logo.jpg", "id": "80559c9a-39ac-4e22-af81-7d7395f45673", "_p3d_type": "urn:primitive:obj:attachment" } }}External link(urn:primitive:obj:external-link)
Section titled “External link(urn:primitive:obj:external-link)”| 字段 | 类型 | 说明 |
|---|---|---|
url | string | 链接目标。 |
text | string | 链接的显示文本。 |
_p3d_type | string | 始终为 urn:primitive:obj:external-link。 |
external link 是自包含的;在元数据写入时直接设置该对象即可,无需上传。
Attachment(urn:primitive:obj:attachment)
Section titled “Attachment(urn:primitive:obj:attachment)”| 字段 | 类型 | 说明 |
|---|---|---|
name | string | 原始文件名。 |
id | string | attachment 的 fileId,从下方的上传流程中获得。 |
_p3d_type | string | 始终为 urn:primitive:obj:attachment。 |
与 external link 不同,attachment 值引用的是一个必须先存在的文件。上传该文件是一个独立的、多步骤的调用序列,将在下文介绍。
将文件附加到元数据
Section titled “将文件附加到元数据”要让一个文件能够作为 attachment 值被引用,需要经过三步流程:发起上传、将分片上传到 S3、完成上传;然后在下一次元数据写入时,将返回的文件 id 作为 attachment 值的 id 字段使用。
| 方法 | 路径 | 作用域 | 用途 |
|---|---|---|---|
POST | /v1/twin/{contextId}/object/attachments | write:asset | 发起附件上传 |
GET | /v1/twin/{contextId}/object/attachments/{fileId}/refresh/{startIndex} | write:asset | 重新签发已过期的分片 URL |
POST | /v1/twin/{contextId}/object/attachments/{fileId}/finalize | write:asset | 完成上传 |
GET | /v1/twin/{contextId}/object/attachments/{fileId}/download | read:asset | 获取签名下载 URL |
DELETE | /v1/twin/{contextId}/object/attachments/{fileId} | write:asset | 移除附件 |
contextId 是该附件所属的孪生体、站点或草稿;与 搜索 business object 时使用的 id 相同。
上传本身遵循 API 中其他地方使用的通用发起 → 分片上传 → 完成机制(分片上传,预签名 S3 URL,过期后可重新签发)。有关该机制及其分片编号的常见陷阱,请参阅共享分片上传参考。本节仅介绍附件特有的内容。
第一步:发起
Section titled “第一步:发起”POST {api_url}/v1/twin/{contextId}/object/attachmentsAuthorization: Bearer {access_token}Content-Type: application/json
{ "fileName": "prevu_logo.jpg", "fileSize": 84213, "mimeType": "image/jpeg" }{ "fileId": "80559c9a-39ac-4e22-af81-7d7395f45673", "parts": 1, "urls": [ { "partNumber": 1, "url": "https://s3…/part-1?…" } ]}第二步:上传分片
Section titled “第二步:上传分片”将每个分片 PUT 到其对应的预签名 url,并保存每个分片返回的 ETag,具体做法与共享分片上传参考中描述的一致。
第三步:完成
Section titled “第三步:完成”POST {api_url}/v1/twin/{contextId}/object/attachments/{fileId}/finalizeAuthorization: Bearer {access_token}Content-Type: application/json
{ "parts": [ { "partNumber": 1, "etag": "\"a1b2c3d4e5f6\"" } ] }{ "fileId": "80559c9a-39ac-4e22-af81-7d7395f45673", "fileName": "prevu_logo.jpg", "size": 84213}第四步:在元数据中引用该文件
Section titled “第四步:在元数据中引用该文件”从完成上传的响应中获取 fileId,并在下一次元数据写入时将其设置为 attachment 值的 id:
PATCH {api_url}/v1/twin/{contextId}/object/{objectId}/metadataAuthorization: Bearer {access_token}Content-Type: application/json
{ "metadata": { "Section name": { "landing image": { "name": "prevu_logo.jpg", "id": "80559c9a-39ac-4e22-af81-7d7395f45673", "_p3d_type": "urn:primitive:obj:attachment" } } }}元数据写入接收的是完整的元数据对象;新增、更新和移除的分区与属性都包含在内;而不是针对单个属性的补丁。因此,在加入新的附件引用的同时,请一并包含所有你想保留的分区和属性。
GET /v1/twin/{contextId}/object/{objectId}/metadata 会按照写入时的原样返回每个属性:简单的 string/number/boolean,或上述两种标记对象之一,且 _p3d_type 保持不变。读取标记值不需要单独的”解析”步骤;对象本身(包括附件的 id)会随元数据响应内联返回。
要获取文件的字节内容,将该 id 作为 fileId 传给下方的下载接口。
下载与删除附件
Section titled “下载与删除附件”GET {api_url}/v1/twin/{contextId}/object/attachments/{fileId}/downloadAuthorization: Bearer {access_token}{ "url": "https://d111111abcdef8.cloudfront.net/…" }返回的 URL 是一个签名的 CloudFront 链接,有效期约为 4 小时。如果过期,请重新获取。
要删除某个附件的底层文件:
DELETE {api_url}/v1/twin/{contextId}/object/attachments/{fileId}Authorization: Bearer {access_token}附件存储使用与 RealityConnect 中其他任何文件相同的按组织分配的存储空间;不存在单独的”附件配额”。
| 问题 | 答案 |
|---|---|
| 单个附件的最大大小 | 未强制实施专门的大小上限。实际上限是你组织剩余的存储空间。 |
| 每个对象的最大附件数量 | 未强制实施专门的数量上限。一个元数据分区可以包含任意数量的 attachment 类型属性。 |
| 每个孪生体或每个组织的总量 | 不存在单独的附件配额。每个附件都作为普通文件存储,并计入你组织的整体存储分配;与其他任何已上传文件使用的是同一个计数器。一旦使用量超过你组织分配的存储空间,就会返回 StorageLimitExceeded(参见错误代码)。该分配额度取决于具体套餐,因此这里无法公布一个统一数字;请与你的 Prevu3D 客户团队确认你组织的具体数字。 |
| 接受的文件类型 | 你发送的任何 mimeType 都会被接受;没有需要满足的允许列表。 |
| 同一文件附加到多个对象 | 每次上传存储一次,而不是每次引用存储一次。两次上传相同的字节内容(两次独立的 initiate → finalize 流程)会创建两个各自存储的文件;不存在自动去重。要将同一份共享文档附加到多个对象而不重复存储,请只上传一次,然后在每个对象的 attachment 值中重复使用返回的 id,而不是重新上传。 |
下一步是什么?
Section titled “下一步是什么?”- 有关通用的发起/上传/完成机制,请参阅共享分片上传参考。
- 有关
contextId的解析方式,请参阅搜索 Business Object 和节点。 - 有关每个操作的完整请求和响应模式,请参阅 API 参考。