附件插件
这个 @cap-js/attachments 软件包是一个 CDS 插件 通过使用 方面 调用 Attachments它还提供了联合呼吁程序一级、易于使用的一体化 SAP 对象存储。 。 。 .
目录
使用量
快速启动
用于快速本地开发的内存存储器:
-
该插件具有所描述的自配置,参见以下细节部分. 要启用附件, 只需在您的工程中添加插件包 :
npm add @cap-js/attachments附件插件需要在耗用 CAP 节点JS 应用程序的软件包中引用 :"dependencies": { "@cap-js/attachments": "<latest-version>", // (...) }此外,可在以下网址中找到不同的简介:
package.json此外,例如:"cds": { "requires": { // (...) "[hybrid]": { "attachments": { "kind": "standard" // (...) } } } } -
要使用附件,请通过添加提及预定义附件类型的元素来扩展一个 CDS 模型(参见 CDS 模型的更改 详情如下:
using { Attachments } from '@cap-js/attachments'; entity Incidents { // (...) attachments: Composition of many Attachments; }
在这个指南中,我们使用 事件管理参考应用样本 作为演示如何使用此插件的基础应用程序。 此应用程序的微型版本可在 测试 用于本地测试的目录.
对于生产性用途,需要装订有效的物品储存,见 对象存储 财务报告和审定财务报表 存储目标。 。 。 .
本地走过
通过上述步骤,我们成功地为我们的参考申请建立了资产处理。 要在当地测试应用程序,请使用以下步骤.
[注] 为本地测试,附件对象被存储在 本地数据库。 。 。 .
- 启动服务器数字 :
- 默认 假想( 内存数据库) :
cds watch
-
导航到对象页面 事件发生时
Solar panel broken数字 : 转到事件对象页面 太阳面板已损坏 -
这个
Attachments类型在对象页下方生成了框外附件表(见1) :
-
上传文件 通过进入编辑模式并使用 上传 按钮。 然后单击 保存 按钮将文件存储在专用资源中(数据库、S3桶等)。 我们通过上传 PDF 文件来证明这一点 测试/整合/内容/样本.pdf数字 :

-
删除文件 通过进入编辑模式,选择文件,并按下 删除 按钮。 点击 保存 按钮然后从资源中删除该文件(数据库、S3桶等).

CDS 模型的更改
用这个方面 Attachments 关于一个现有实体,相应的实体需要将附件作为要素列入模型定义,或者在CDS文件中扩展 srv 模块。 在快速启动时,前者就完成了,在模型定义中增加了一个要素:
using { Attachments } from '@cap-js/attachments';
entity Incidents {
// ...
attachments: Composition of many Attachments;
}
实体事件也可以在 srv 模块,见以下示例:
using { Attachments } from '@cap-js/attachments';
extend my.Incidents with {
attachments: Composition of many Attachments;
}
service ProcessorService {
entity Incidents as projection on my.Incidents
}
两种方法都直接添加了相应的UI Facet. 要使用带有 SAP Fiori 元素的插件, 请确定 draft 已启用 用于使用 @odata.draft.enabled。例如:
annotate service.Incidents with @odata.draft.enabled;
如果您不使用 SAP Fiori 元素,则不需要草稿启用 。 更多信息见 非草稿上传 用于替代上传流程.
单个附件
通过将附件域定义为单个附件,也可以只允许一个附件. 这显示了不同的UI,它更清晰地显示单个附件而不是列表中.
using { Attachment } from '@cap-js/attachments';
entity Incidents {
...
attachment: Attachment;
}
存储目标
当本地测试时,插件在没有专用存储目标的情况下运行,直接将附件存储在基础数据库中. 在混合设置中,偏好指定存储目标. 你可以通过使用 cds bind 命令,如 CAP 混合测试文件。 。 。 .
同时,如果有一个专门的存储目标,附件不会被存储在基础数据库中;相反,它被保存在指定的存储目标上,并且按照CDS模型的定义,只将一个包括元数据的参考文件保存在数据库中.
对于在 BTP 中使用对象存储器, 您必须在创建的合适地貌上已有 SAP 对象存储器服务实例 。 要将其绑入混合设置,请跟踪此设置:
- 登录到 Cloud Foundry :
cf login -a <CF-API> -o <ORG-NAME> -s <SPACE-NAME> --sso
- 要绑定到服务, 在工程目录中通过运行生成一个新的文件 . cdsrc-private.json :
cds bind <HybridObjectStoreName> --to <RemoteObjectStoreName>
何处 HybridObjectStoreName 可以是用户在此给出的任何名称,并且 RemoteObjectStoreName 是您在 SAP BTP 中对象存储实例的名称.
- 要以混合模式运行应用程序, 请运行命令 :
cds watch --profile hybrid
见 对象存储 关于SAP对象存储的更多信息.
恶意扫描器
BTP 恶意软件扫描服务用于 AttachmentService 以扫描附件以识别弱点.
用于使用 SAP 恶意软件扫描服务,您必须已经有一个您可以访问的服务实例。 要绑定它,请执行以下命令:
cds bind <HybridMalwareScannerName> --to <RemoteMalwareScannerName>
默认情况下,如果指定了存储提供者,所有配置文件都会启用恶意软件扫描. 您可以通过设置配置恶意软件扫描 :
{
"cds": {
// (...)
"attachments": {
"scan": true
}
}
}
如果没有恶意软件扫描仪可用,且扫描仪没有被禁用,那么上传就会失败.
扫描状态代码 :
Unscanned:附件仍未扫描.Scanning:上传后立即将附件标为"扫描". 根据处理速度的不同,在重新装入页面时它可能已经作为Clean出现.Clean: 只有带有状态 Clean 的附件可以访问.Infected:附件被感染了.Failed: 扫描失败.
[!注] 恶意软件扫描仪支持mTLS认证,这需要每年更新证书. 以前使用的基本认证现已贬值.
[!注] 如果恶意软件扫描仪报告的文件大小大于通过指定的限制 @Validation. (原始内容存档于2018-09-26). 最大值 它删除文件并设置附件元数据失败状态.
速率限制处理( 自动重试)
SAP Malware Scanning Service执行每个子账户30个并行请求的费率限制。 当超过此限制时, 服务会响应 HTTP 429 Too Many Requests。默认情况下,插件会自动重复扫描请求,这些请求会使用与 jitter 的指数回放接收429个回复.
您可以配置重试行为 package.json 或者说 .cdsrc.json数字 :
{
"cds": {
"requires": {
"malwareScanner": {
"retry": {
"maxAttempts": 5,
"initialDelay": 1000,
"maxDelay": 30000
}
}
}
}
}
| 选项 | 默认 | 说明 |
|---|---|---|
retry.maxAttempts | 5 | 包括初步请求在内的尝试总数 |
retry.initialDelay | 1000 | 在第一次重试前以毫秒为基数的延迟 |
retry.maxDelay | 30000 | 重试之间的最大延迟( 毫秒) |
当429项反应包括: Retry-After 页眉,插件尊重该值(封顶于 maxDelay) (中文(简体) ). 只有429个反应触发了重复——其他错误立即失效.
无法重试并恢复先前的行为( 立即在 429 上失败) set retry 改为 false。 。 。 .
扫描货币限制
为了减少共享费率限制的压力,插件限制在一个单一的进程中同时运行的扫描请求数量. 超时扫描在槽可用时排队并进行处理.
{
"cds": {
"requires": {
"malwareScanner": {
"maxConcurrentScans": 10
}
}
}
}
| 选项 | 默认 | 说明 |
|---|---|---|
maxConcurrentScans | 30 | 每个过程同时扫描请求的最大数量. 设定为 0 以禁用(未限制的平行). |
由于429个响应而正在重试的扫描在回放等待时会保持其同位素槽,防止重试风暴与新扫描相竞争.
自动重新扫描文件
根据欧洲委员会的建议 恶意扫描服务如果上次扫描超过3天,则附件应自动重新扫描。 通过指定 scanExpiryMs 属性 :
{
"cds": {
"requires": {
"attachments": {
"scanExpiryMs": 259200000
}
}
}
}
默认, scanExpiryMs 设置为 259200000 毫秒(3天). 不允许下载附件, 除非其状态是 Clean。 。 。 .
审计记录
附加服务发布以下三个事件:
- 附件下载已拒绝,
- 已执行附件,
- 附件上载已拒绝
何时 @cap-js/audit-logging 3个事件会自动被记录为 审计日志服务中的安全事件 .
您可以为这三起事件注册自定义处理器 :
const attachments = await cds.connect.to("attachments")
attachments.on("AttachmentDownloadRejected", (msg) => {})
附件的可见控制 UI Facet 生成
通过设置 @UI.Hidden 属性改为 true,开发者可以在UI中隐藏插件的能见度. 在插件的能见度需要根据某些条件动态控制的情况下,这个特性特别有用.
示例使用
entity Incidents {
// ...
@UI.Hidden
attachments: Composition of many Attachments;
}
在这个例子中 @UI.Hidden 设置为 true,这意味着插件默认会被隐藏。 也可以使用动态表达式,然后添加到面部.
entity Incidents {
// ...
status : Integer enum {
submitted = 1;
fulfilled = 2;
shipped = 3;
canceled = -1;
};
@UI.Hidden : (status = #canceled ? true : false)
attachments: Composition of many Attachments;
}
复制附件
这个 AttachmentsService 暴露一个方案 copy() 复制新记录附件的方法。 在云存储后端(AWS S3,Azure Blob Survey,GCP Cloud Survey)上,这个版本使用后端-内置服务器-侧式副本——没有通过您应用程序传输二进制数据. 在数据库存储时,它直接读取并插入内容.
签署:
const AttachmentsSrv = await cds.connect.to("attachments")
await AttachmentsSrv.copy(
sourceAttachmentsEntity,
sourceKeys,
targetAttachmentsEntity,
(targetKeys = {}),
)
| 参数 | 说明 |
|---|---|
sourceAttachmentsEntity | CDS实体定义源附件构成. |
sourceKeys | 附件的密钥( 如 . { ID: '...' }(中文(简体) ) |
targetAttachmentsEntity | CDS实体定义目标附件组成. |
targetKeys | 用于新记录(如. { up__ID: '...' }) (中文(简体) ). 何时 targetAttachmentsEntity 表格草稿,还必须包括: DraftAdministrativeData_DraftUUID。 。 。 . |
扫描 status, (中文(简体) ), lastScan,以及 hash 从源头继承——由于二进制内容完全相同,因此没有再扫描被触发. 状态不时复制附件 Clean 以 400 错误.
[注] 只有同一房客内部的复印件才有支持。 交叉租户副本是不可能的.
实例
复制两个活动记录 :
const { Incidents } = ProcessorService.entities
await AttachmentsSrv.copy(
Incidents.attachments,
{ ID: sourceAttachmentID },
Incidents.attachments,
{ up__ID: targetIncidentID },
)
复制到新的记录草稿(例如从模板创建事件)
const { Incidents } = ProcessorService.entities
// Look up the draft session UUID for the target incident's open draft
const targetDraft = await SELECT.one
.from(Incidents.drafts, { ID: targetIncidentID })
.columns("DraftAdministrativeData_DraftUUID")
await AttachmentsSrv.copy(
Incidents.attachments,
{ ID: sourceAttachmentID },
Incidents.attachments.drafts,
{
up__ID: targetIncidentID,
DraftAdministrativeData_DraftUUID:
targetDraft.DraftAdministrativeData_DraftUUID,
},
)
程序查询附件
因为 Attachments 是一个标准的 CDS 组成,因此可以直接使用 cds.ql (中文(简体) ) 与查询联合呼吁程序服务中的任何其他实体的方式相同.
该实体完全有资格使用其名称 "<Entity>.attachments" 通过 service.entities,例如:
const Attachments = ProcessorService.entities["Incidents.attachments"]
用于给定父记录的附件元数据(ID, 文件名, mimeType, 状态, lastScan, note, createAt, createBy) 可以使用 SELECT.from。注意二进制内容字段默认被排除,使操作轻量级:
const attachmentsMeta = await SELECT.from(Attachments).where({
up__ID: incidentID,
})
这个 up__ID 栏是自动生成的返回母记录的外国密钥。 后面的后缀 up__ 是母实体的密钥字段名(如:. ID) (中文(简体) ).
非草稿上传
例如,对于该实体未获得草稿的情景 tests/non-draft-request.http,需要手动执行单独的HTTP元数据创建和资产上传请求.
典型序列包括:
- 邮政 - > 创建附件元数据, 返回ID
- 点 - > 使用ID上传文件内容
指定最大文件大小
您可以通过注释附件内容属性来指定最大文件大小 @Validation.Maximum
entity Incidents {
...
attachments: Composition of many Attachments;
}
annotate Incidents.attachments with {
content @Validation.Maximum : '20MB';
}
默认为 400MB
限制允许的 MIME 类型
您可以通过注释内容属性来限制哪些 MIME 类型被允许附加 @Core.AcceptableMediaTypes。此验证在文件上传时进行.
entity Incidents {
...
attachments: Composition of many Attachments;
}
annotate Incidents.attachments with {
content @Core.AcceptableMediaTypes : ['image/jpeg', 'image/png', 'application/pdf'];
}
支持通配符模式 :
annotate Incidents.attachments with {
content @Core.AcceptableMediaTypes : ['image/*', 'application/pdf'];
}
要允许所有 MIME 类型( 默认行为) , 要么省略注释, 要么使用 :
annotate Incidents.attachments with {
content @Core.AcceptableMediaTypes : ['*/*'];
}
当一个被否决的 MIME 类型的文件被上传时, 请求会用一个 400 错误.
内置浏览器预览
默认情况下,附件被送达 Content-Disposition: attachment,它迫使一个文件下载并阻止浏览器渲染内容内线。 这是安全的默认值, 用来防止 XSS 攻击中存储的文件, 当打开时会执行程序的来源 .
为了启用内置浏览器预览(即PDF和图像在浏览器标签中直接打开而不是下载),设置 inline cDS配置中的旗帜 :
"cds": {
"requires": {
"attachments": {
"inline": true
}
}
}
安全说明: 当启用内置预览时, 您应该将允许的 MIME 类型限制为使用安全许可列表
@Core.AcceptableMediaTypes来防止脚本文件类型被上传。 类型,例如:image/svg+xml, (中文(简体) ),text/html,以及application/xhtml+xml可以在浏览器内出时执行嵌入式JavaScript,并应排除:annotate Incidents.attachments with { content @Core.AcceptableMediaTypes : ['image/jpeg', 'image/png', 'application/pdf']; }
最小和最大附件数量
您可以使用 @Validation.MaxItems 财务报告和审定财务报表 @Validation.MinItems 说明。 这些说明定义了可以关联到一个实体的文件的最大和最小数量.
以2个附件为限
entity Incidents {
...
@Validation.MaxItems: 2
attachments: Composition of many Attachments;
}
要求至少2个附件
entity Incidents {
...
@Validation.MinItems: 2
attachments: Composition of many Attachments;
}
允许覆盖附件内容
默认情况下 Attachments 边框注释实体 @Capabilities.UpdateRestrictions.NonUpdatableProperties: [content],防止覆盖现有附件的内容。 任何试图将新内容上传到已拥有内容的附件的尝试都将被拒绝 409 Conflict 错误.
为了允许覆盖附件内容, 请在附件构成上用空数组覆盖注释 :
using { Attachments } from '@cap-js/attachments';
entity Incidents {
...
attachments: Composition of many Attachments;
}
// Allow content to be overwritten
annotate Incidents.attachments with
@Capabilities.UpdateRestrictions.NonUpdatableProperties: [] {};
有了这个注释后,将新内容通过 PUT 来覆盖现有内容,而不是返回 409 错误.
[注] 此注释会在所有存储后端运行时进行评估 。 当允许内容覆盖时,上传到已存在的附件会替换所存储的文件.
复制文件名称
当多个具有相同文件名的附件被上传到同一个母实体时,插件可以通过附加一个数字后缀(例如. report.pdf, (中文(简体) ), report-1.pdf, (中文(简体) ), report-2.pdf) (中文(简体) ). 这既适用于单上传,也适用于深插入.
行为默认启用 。 要禁用, 请设定 deduplicateFileNames 改为 false 在附件配置中:
{
"cds": {
"requires": {
"attachments": {
"deduplicateFileNames": false
}
}
}
}
释放
最小 UI5 和 CAP 节点JS 版本
| 构成部分 | 最小版本 |
|---|---|
| CAP 节点 | 8.0.0 (单位:千美元) |
| 用户界面5 | 1.136.0 (韩语) |
结构概览
多重性
该插件支持多租期方案,允许共享和租户专用对象存储实例.
[!注] 从2.1.0版本开始, 单独模式 用于对象存储实例的默认设置.
对于多租户申请, @cap-js/attachments 必须在申请级别和 mtx/侧车/包.json 文档.
单独的对象存储实例
默认情况下,插件会在租户订阅期间为每个租户创建自己的对象商店实例.
当租户不订阅时,对象存储实例被删除.
[尖叫声] 当单独对象商店已经创建后从应用程序中删除插件时,对象商店不会被自动删除!
共享对象存储实例
要配置一个共享对象存储实例, 将两个软件包. json 文件修改如下 :
"cds": {
"requires": {
"attachments": {
"objectStore": {
"kind": "shared"
}
}
}
}
为了确保在使用共享对象存储实例时的租户身份,插件会用租户ID前缀附件URL. 确定共享对象存储实例与 mtx 部署前的应用模块.
对象存储
需要有效的对象存储服务装订,一般通过SAP BTP提供. 见 存储目标 财务报告和审定财务报表 部署到云铸厂 关于如何使用此对象存储服务绑定.
部署到云铸厂
表格中的相应条目 mta 文档 可能看起来像:
_schema-version: '0.1'
ID: consuming-app
version: 1.0.0
description: "App consuming the attachments plugin with an object store"
parameters:
...
modules:
- name: consuming-app-srv
# ------------------------------------------------------------
type: nodejs
path: srv
parameters:
...
properties:
...
build-parameters:
...
requires:
- name: consuming-app-hdi-container
- name: consuming-app-uaa
- name: cf-logging
- name: **object-store-service**
...
resources:
...
- name: **object-store-service**
type: org.cloudfoundry.managed-service
parameters:
service: objectstore
service-plan: standard
测试
此模块中的单元测试不需要绑定相应的对象存储, 运行它们 npm install。为了实现一个干净的安装,命令 rm -rf node_modules 安装前应使用.
为本地测试 Postgres 数据库, 请创建 Podman (或 Docker) 容器并运行命令 podman compose -f tests/pg.yml up -d。每一次集装箱被停放时,都应运行该程序。 在初始设置时,数据库必须部署在 npm run deploy:postgres从那时起,用Postgres进行测试就很简单了 npm run test:postgres。关于邮局设置的更多信息,请参见官方网站 Capire 文档。 。 。 .
集成测试需要绑定一个真实对象商店. 跟着他们跑 npm run test。 。 。 .
要设置绑定,请参见该节 存储目标。 。 。 .
支持的存储提供者
- 标准 (单位:千美元)
kind: "standard"QQ 取决于绑定对象存储证书,使用 AWS S3, Azure Blob 存储或 GCP Cloud 存储. 您可以通过调整类型来手动指定执行 :- AWS S3 导弹 (单位:千美元)
kind: "s3"(中文(简体) ) - Azure Blob 存储器 (单位:千美元)
kind: "azure"(中文(简体) ) - GCP 云存储器 (单位:千美元)
kind: "gcp"(中文(简体) )
- AWS S3 导弹 (单位:千美元)
示范文本
在模型中,几个字段附加了 @title 注释。 默认文本提供于 2种语言。如果这些缺省不足以用于应用程序,则可以用自定义文本或翻译的应用程序来覆盖.
下表概述了各个字段和i18n代码:
| 字段名称 | i18n 代码 |
|---|---|
mimeType | MediaType |
fileName | FileName |
status | ScanStatus |
note | note |
除字段名称外,页眉信息(@UI.HeaderInfo并附加说明:
| 标题信息 | i18n 代码 |
|---|---|
TypeName | Attachment |
TypeNamePlural | Attachments |
监视日志( L)
要配置附件插件的日志, 请在 package.json 使用量:
{
"cds": {
"log": {
"levels": {
// (...)
"attachments": "debug"
}
}
}
}
...
支助、反馈和贡献
此项目可通过下列方式对特性请求/建议、错误报告等开放: GitHub 问题鼓励并始终欢迎各方作出贡献和反馈。 关于如何作出贡献的更多信息,项目结构、 地方发展设置以及补充资料,见我们 贡献准则。 。 。 .
行为守则
作为成员、贡献者和领导人,我们保证使参加我们的社区成为每个人不受骚扰的经历。 通过参与这个项目,你同意遵守 行为守则 在任何时间.
许可证发放
版权2024 SAP SE或SAP下属公司和贡献者. 请看我们的 自由主义 版权和许可证信息。 详细信息,包括第三方组成部分及其许可证/版权信息 通过REUSE工具。 。 。 .