文件包
由Amazon S3支持的文件存储.
何时使用 : 您需要存储,检索,或服务二进制文件——用户上传,生成报告,图像,视频,或静态资产.
不使用时 : 如果您需要结构化的密钥值数据并附带条件的写入,请使用 KVStore。如果需要带有索引的可查询记录,请使用 DistributedTable。 。 。 .
设计与模拟等价细节 : 设计
API 密码
const bucket = new FileBucket(scope, id, options?)
| 方法 | 回返 | 说明 |
|---|---|---|
put(path, body, options?) | Promise<void> | 上传文件 。 覆盖路径上的任何已存在文件. |
get(path, options?) | Promise<FileContent | null> | 下载文件 。 回返 null 如果缺席。 过 { versionId } 在版本桶上. |
delete(path, options?) | Promise<void> | 删除文件 。 如果缺席就不行 过 { versionId } 要永久删除一个版本. |
deleteBatch(paths) | Promise<void> | 删除多个文件 。 内部1000个键. |
getUrl(path, options?) | Promise<string> | 生成一个预先签名的下载 URL 。 接受 versionId 在版本桶上. |
putUrl(path, options?) | Promise<string> | 生成一个预先签名的上传 URL . |
getFileHandle(path, options?) | Promise<FileDownloadClient> | 获取浏览器侧面使用的下载控件. 接受 versionId 在版本桶上. |
createUploadHandle(path, options?) | Promise<FileUploadClient> | 获取浏览器侧面使用的上传控件 . |
scan(options?) | AsyncIterable<FileInfo> | 列出文件. 使用 prefix 到范围. |
listVersions(path) | Promise<FileVersionInfo[]> | 列出一个文件的所有版本( 只有版本桶) 。 最新的第一个. |
restoreVersion(path, versionId) | Promise<void> | 将上一版本恢复为当前版本 . |
FileBucket.fromExisting(bucketName) | ExternalBucketRef | 包装一个先前存在的S3桶. |
选项
| 选项 | 类型 | 说明 |
|---|---|---|
versioned | boolean | 启用 S3 对象版本 . 默认 : true。 。 。 . 过 versioned: false 选择退出。 注: 版本识别方法打字(versionId 打开 get编号 :delete编号 :getUrl编号 :getFileHandle) 仅由文字选择 versioned: false; 非读取 boolean 或者一个缺失的值解决了版本的识别打字. |
noncurrentVersionExpirationDays | number | 天数 非当前 (被取代的)对象版本永久过期,限定了版本否则会让其生长无限制的存储成本. 只有在版本被启用时(默认)才适用. 默认 : 90。 。 。 . 必须是正整数——非正值或非正值投向合成. 没有禁用发送器; 要完全丢弃规则, 禁用版本( S)versioned: false) (中文(简体) ). 被模拟器和浏览器运行时间所忽略. |
corsRules | CorsRule[] | CORS规则基于浏览器的访问. 默认: 无 —— 浏览器屏蔽每个交叉源代码 fetch() 在部署的桶. 当浏览器代码直接获取一个预先签名的 URL 时, 要求 download() 编号 : upload() 在文件控件上,或 fetch() 编号 getUrl() 编号 : putUrl() URL)针对部署的沙盒或生产堆. 未从堆栈继承 defaults.allowedOrigins 或主机域。 忽略当 bucket 覆盖一个已有的桶。 见 浏览器上传和下载( CORS),以及 规则 给来自通配符的合成警卫. |
lifecycleRules | LifecycleRule[] | 自动到期或存储类过渡的生命周期规则. |
accessLogging | boolean | 启用 S3 服务器访问日志 . 默认: 倒回堆栈姿态( E)BlocksDefaults.storageAccessLogging,则 BlocksDefaults.accessLogging(中文(简体) ) 当省略时——这样一个堆栈可以选择每个FileBucket进行记录,而不需要每个块的标记. 当启用时,会提供一个专用的,被锁定的日志桶(所有公共访问被屏蔽,S3管理加密,SSL强制),主桶会在那里发送访问日志 access-logs/ 前缀。 访问日志在堆栈姿态后自动过期 logRetention (单位:千美元)ONE_WEEK 沙盒内/ ONE_YEAR 生产中; RetentionDays.INFINITE 永远保持他们。 被模拟器和浏览器运行时间所忽略. |
encryption | 'aws-managed' | 'customer-managed' | ExternalKmsKeyRef | 服务器侧加密休息 . 默认 : 'aws-managed' (SSE-S3) (英语). 'customer-managed' 为这个桶创建一个专用的 KMS 密钥( 旋转上, 用桶取出 ); FileBucket.fromKmsKey(arn) 使用您已经拥有的密钥。 两者都使用带有S3 Bucket键的SSE-KMS. 见 用 KMS 加密。被忽略,带有合成警告 bucket 覆盖一个已有的桶。 被模拟器和浏览器运行时间所忽略. |
objectLock | { mode: 'governance' | 'compliance'; retentionDays: number } | 启用 S3 对象锁定, 每个新对象版本都有默认保留 . 默认:关闭. 需要版本和保留桶(removalPolicy: 'retain' 在沙盒中); 两者在合成时检查。 只能在桶初创建时设置 。 指定上传( N)putUrl, (中文(简体) ), createUploadHandle在这些桶上不支持——上传到 put()。见 对象锁定。被忽略,带有合成警告 bucket 覆盖一个已有的桶。 由"模拟"验证,但未执行. |
bucket | ExternalBucketRef | 将已有的 S3 桶包起来, 而不是创建 . |
logger | ChildLogger | 内部操作的可选日志。 在省略时,会创建默认错误级日志 . |
removalPolicy | 'destroy' | 'retain' | 基础 S3 桶的 CCDK 移除行为 。 省略时,它会倒回堆栈姿态默认值(BlocksDefaults.removalPolicy —— 说 DESTROY 在沙盒中, RETAIN 生产中);通过 'destroy' 或者说 'retain' 将它清晰地设置在每一个街区. 'destroy' 还启用 autoDeleteObjects 这样,桶可以被清空 在撕下。 被模拟器和浏览器运行时间所忽略. |
全部文件桶设置 无条件执行 TLS (单位:千美元)enforceSSL: true——CDK附加了桶子政策,拒绝在下列情况下的任何请求: aws:SecureTransport 实值 false,缩小过境接触差距。 此相相相相无相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相.
S3桶名来源于瞄准镜链:FileBucket id加入到其母瞄准镜ID中 -。如果该名称符合S3的63个特征限制,则按原样使用。 如果更长,就缩短到名字开始加 - 和一个8个特征的散列。 每次部署都使用相同的简称,与其他桶的名字不同。 一个打破 S3 任何其他命名规则的名称( 例如, 一个带有大写字母) 仍然失败 cdk synth 带有 ValidationFailed 错误。 要读取已解决的名字, 请打电话 getSdkIdentifiers(bucket).bucketName (从) @aws-blocks/blocks) (中文(简体) ).
设置选项
| 选项 | 类型 | 说明 |
|---|---|---|
contentType | string | MIME 类型(例如, image/png) (中文(简体) ). 默认 : application/octet-stream。 。 。 . |
metadata | Record<string, string> | 自定义元数据密钥值对 . |
cacheControl | string | 缓存控制头值 . |
指定 URL 选项
getUrl, (中文(简体) ), putUrl, (中文(简体) ), getFileHandle,以及 createUploadHandle 接受 expiresIn 在几秒钟。 必须是整数从 1 改为 604800 (7天);默认为 3600。 。 。 .
规则
用于基于浏览器访问的 CORS 配置 。 通过 corsRules 选项.
| 外地 | 类型 | 说明 |
|---|---|---|
allowedOrigins | string[] | 允许提出跨来源请求的来源(例如:, ['https://app.example.com']) (中文(简体) ). |
allowedMethods | ('GET' | 'PUT' | 'POST' | 'DELETE' | 'HEAD')[] | 允许跨源请求使用HTTP方法. |
allowedHeaders | string[] | 可选的 实际请求中允许请求信头. |
exposedHeaders | string[] | 可选的 被浏览器曝光的反应头. |
maxAge | number | 可选的 秒浏览器可能缓存飞行前的响应. |
通配符起源和变异方法: a 结合通配符来源的CORS规则(
'*') 有变异方法(PUT, (中文(简体) ),POST,或DELETE(中文(简体) ) 丢入合成 它将让任何网站发布改变状态的跨原产地请求。 指定明确的来源(例如:.['https://app.example.com'])用于变异方法. 只有一个安全方法的通配符来源(GET编号 :HEAD)被允许.
寿命周期规则
用于自动到期或存储级过渡的生命周期配置. 通过 lifecycleRules 选项.
| 外地 | 类型 | 说明 |
|---|---|---|
prefix | string | 可选的 前缀过滤器——规则只适用于从此前缀开始的密钥. 关闭以适用于所有对象 . |
expirationDays | number | 可选的 创建后天数为过期对象( 删除) . |
transitionToIaDays | number | 可选的 创建后数天向不频繁访问存储过渡对象. |
文件服务器信息
归来 listVersions() ——每个对象版本一个条目,最先更新.
| 外地 | 类型 | 说明 |
|---|---|---|
versionId | string | 版本标识符. |
lastModified | Date | 此版本创建时. |
size | number | 大小为字节. |
isCurrent | boolean | 是否为当前( 最新) 版本 . |
处理错误
get() 返回时 null 丢失的文件,它确实 没有 掷出 FileNotFound。检查无效 :
const file = await bucket.get('missing.txt');
if (!file) {
// file does not exist
}
FileBucketErrors 被其他操作抛出,并与 isBlocksError数字 :
| 常数 | error.name | 掷出时 |
|---|---|---|
FileBucketErrors.FileNotFound | NoSuchKey | 由前署名的URL 404等出场. 没有 抛出 get()返回时 null。 。 。 . |
FileBucketErrors.FileTooLarge | EntityTooLarge | 文件超过大小限制 . |
FileBucketErrors.VersionNotFound | NoSuchVersion | 被丢弃 restoreVersion() 当目标 versionId 无法解决. |
FileBucketErrors.PresignedUploadUnsupported | PresignedUploadUnsupported | 被丢弃 putUrl() 财务报告和审定财务报表 createUploadHandle() 装入桶里 objectLock 看到了吗 对象锁定。 。 。 . |
import { isBlocksError } from '@aws-blocks/core';
import { FileBucketErrors } from '@aws-blocks/bb-file-bucket';
try {
await bucket.restoreVersion('report.pdf', 'non-existent-version');
} catch (e: unknown) {
if (isBlocksError(e, FileBucketErrors.VersionNotFound)) {
// that version does not exist
}
throw e;
}
实例
基本布置/获取
const bucket = new FileBucket(scope, 'uploads');
export const api = new ApiNamespace(scope, 'api', (context) => ({
async uploadFile(name: string, content: string) {
await bucket.put(name, content, { contentType: 'text/plain' });
},
async getFile(name: string) {
const file = await bucket.get(name);
if (!file) return null;
return { contentType: file.contentType, size: file.size };
},
}));
已指定上传 URL
const bucket = new FileBucket(scope, 'media');
export const api = new ApiNamespace(scope, 'api', (context) => ({
async getUploadUrl(path: string) {
const url = await bucket.putUrl(path, {
expiresIn: 600,
contentType: 'image/jpeg',
});
return { uploadUrl: url };
},
}));
浏览器上传和下载( CORS)
浏览器获取指定 URL 和文件控件 直接取自 S3,这个来源与您的前端不同。 因此,部署的桶必须允许 您的前端的源头通过 corsRules。文件包配置 默认无 CORS与API的终点不同,它确实 没有 捡起堆栈 defaults.allowedOrigins 或主机域。 没有匹配规则,每个浏览器上传或下载到已部署的沙盒或生产堆栈都会失败:
Access to fetch at 'https://<bucket>.s3.<region>.amazonaws.com/...' from origin 'http://localhost:3000'
has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
对于 upload() 编号 : PUT,而浏览器在飞行前失败,信件继续 Response to preflight request doesn't pass access control check: 在同一个文本之前.
npm run dev 不显示此值: 本地 dev 文件服务器接受任何来源, 因此错误在您部署后首先出现 .
列出您前端来自本地 dev 前端的每个来源(http://localhost:3000当它与一个部署的沙盒交谈时) 和你的部署的应用程序的来源。 与主机,这是堆 HostingUrl 输出: 如果您配置了一个自定义域, 否则生成 https://<id>.cloudfront.net 域名,仅在第一次部署后存在(一次部署,副本) HostingUrl 输入 corsRules,然后重新部署:
const bucket = new FileBucket(scope, 'uploads', {
corsRules: [{
allowedOrigins: ['http://localhost:3000', 'https://app.example.com'],
allowedMethods: ['GET', 'PUT'],
allowedHeaders: ['Content-Type'],
}],
});
aws-blocks/index.ts 由沙盒和生产部署共享,因此这一规则也允许 http://localhost:3000 在生产桶上。 只有沙盒需要它;将它留在生产中是低风险的,因为预先签名的URL通过他们的查询字符串签名进行认证,而不是环境浏览器证书.
GET覆盖download()财务报告和审定财务报表fetch()编号getUrl()URL( URL ) ;PUT覆盖upload()(单位:千美元)putUrl()URL (中文(简体) ).allowedHeaders必须列出浏览器发送的每个信头。 一个跨源PUT总是触发CORS预飞,如果请求标题如:Content-Type那个upload()——不允许发送.allowedOrigins条目是 S3 源字符串(scheme + 主机 + 端口,没有后继斜线),可选择使用单个*通配符, 如https://*.example.com——不使用regex图案defaults.allowedOrigins。 。 。 .- 使用确切的来源
PUT, (中文(简体) ),POST,以及DELETE。一个赤裸的'*'源头,以变异方法抛出合成(参见 规则); 部分通配符,例如https://*不被捕获,所以避免它用于变异方法. - 普通导航到 a
getUrl()URL (中文(简体) )<img src>, (中文(简体) ),<a href>(c) 非中央遥感组织的要求和工作没有规则;fetch(), (中文(简体) ),download(),以及upload()需要一个. exposedHeaders(例如ETag或者说x-amz-version-id) 仅在定制时需要fetch()代码读取响应头;内置的手柄没有. 每个PUT飞行前,所以maxAge(例如3000)每上传一次会节省回程.- CORS 是桶配置: 更改后重新部署
corsRules。 。 。 . corsRules当bucket覆盖已存在的桶(参见 环绕已存在的桶——在该桶本身上配置CORS.
以扫描方式列出文件
const bucket = new FileBucket(scope, 'reports');
export const api = new ApiNamespace(scope, 'api', (context) => ({
async listReports(yearMonth: string) {
const files: FileInfo[] = [];
for await (const file of bucket.scan({ prefix: `reports/${yearMonth}/` })) {
files.push(file);
}
return files;
},
}));
删除批次
const bucket = new FileBucket(scope, 'tmp');
export const api = new ApiNamespace(scope, 'api', (context) => ({
async cleanupTemp(paths: string[]) {
await bucket.deleteBatch(paths);
},
}));
环绕已存在的桶
const bucket = new FileBucket(scope, 'legacy', {
bucket: FileBucket.fromExisting('my-existing-bucket'),
});
被包裹的桶不接受FileBucket的安全默认. 当你供应时
bucket, FileBucket 绑定在已存在的桶上并提前返回——它通常适用的安全默认没有应用:不是enforceSSL,版本/非当前版本过期,服务器访问日志,blockPublicAccess,加密,或corsRules或通配符-CORS护卫。 您拥有该桶的安全姿态; 在桶上自行配置这些( 或者通过自己的 CDK 构造) , 然后把它包起来 .
已版本弹匣
版本为 默认,所以版本感知方法(listVersions, (中文(简体) ), restoreVersion选择 versionId 打开 get编号 :delete编号 :getUrl编号 :getFileHandle)无任何选择。 过 versioned: false 选择退出( 也可以删除 versionId 选项打字)。 下面的例子过去 versioned: true 为明确起见:
const bucket = new FileBucket(scope, 'docs', { versioned: true });
export const api = new ApiNamespace(scope, 'api', (context) => ({
async upload(name: string, content: string) {
await bucket.put(name, content);
},
async getVersion(name: string, versionId?: string) {
return await bucket.get(name, versionId ? { versionId } : undefined);
},
async listVersions(name: string) {
return await bucket.listVersions(name);
},
async restore(name: string, versionId: string) {
await bucket.restoreVersion(name, versionId);
},
}));
访问日志
进入 S3 服务器访问日志 。 提供了专用的、已锁定的日志桶, 访问日志在堆栈姿态后自动过期 logRetention (单位:千美元)ONE_WEEK 在沙盒中, ONE_YEAR 在生产中:
// Logs delivered to a separate locked-down bucket.
// Retention follows the stack posture's logRetention default — not a per-block option.
const bucket = new FileBucket(scope, 'uploads', {
accessLogging: true,
});
在不启用 API 网关访问日志的情况下, 打开 S3 访问日志 storageAccessLogging 堆栈默认值 :
await BlocksStack.create(app, stackName, {
// ...
defaults: { ...BlocksPresets.production, storageAccessLogging: true },
});
用 KMS 加密
对象默认使用S3管理的密钥(SSE-S3)加密. 要控制密钥, 请使用客户管理的 KMS 密钥 :
// A dedicated key for this bucket (yearly rotation, removed with the bucket).
const invoices = new FileBucket(scope, 'invoices', { encryption: 'customer-managed' });
// Or share a key you already own across buckets and tables.
const key = FileBucket.fromKmsKey('arn:aws:kms:us-east-1:111122223333:key/abcd-1234');
const exports = new FileBucket(scope, 'exports', { encryption: key });
该运行时间角色被授予 kms:Decrypt 编号 : kms:GenerateDataKey* 钥匙,所以 put编号 :get 和预签名的 URL 继续工作。 对于您自己带来的钥匙,其关键政策必须在账户中委托IAM(默认的关键政策确实如此)。 KMS增加了每月的密钥充电;S3 Bucket Keys保持每个请求的KMS充电低.
对象锁定
保护文件不被覆盖或永久删除固定时期( write-once-read-many) :
const auditLog = new FileBucket(scope, 'audit-log', {
objectLock: { mode: 'governance', retentionDays: 365 },
});
每个新版本都锁定 retentionDays。 。 。 . delete(path) 仍然隐藏文件( S3 添加了删除标记), 但永久删除锁定的版本 delete(path, { versionId }) 失败, 直到锁过期 。 单位 'compliance' 模式中包括账户根用户在内的任何人都不能提前删除已锁定的版本; 'governance' 模式允许主机使用 s3:BypassGovernanceRetention 这样做.
通过后端上传 . S3 需要签名 Content-MD5 或者每个上传到对象锁定桶上的校验和页眉。 在已知文件之前就创建了预先签名的URL,因此无法携带一个,而S3拒绝上传. 这些桶上 putUrl() 财务报告和审定财务报表 createUploadHandle() 掷出 FileBucketErrors.PresignedUploadUnsupported 而不是返回一个失败的 URL . put() 成功了,因为SDK增加了验收和. 下载( E)getUrl(), (中文(简体) ), getFileHandle())不受影响.
对象锁定只能由水桶首次被部署时开启,无法被关闭. 锁好的物品也挡住倒地,所以必须保留桶子——通过 removalPolicy: 'retain' 当在沙盒中使用对象锁定时.
最佳做法
- 使用路径前缀来组织文件(例如,
uploads/{userId}/, (中文(简体) ),reports/) (中文(简体) ). 如果某一段可以包含 URL 形状或特殊字符( 例如 OIDC)userId联 合 国${iss}:${sub}喜欢https://issuer:sub,把它包起来encodeURIComponent()第一——未编码//是一个空路段, FileBucket 拒绝它 (ValidationFailed)在本地模拟和AWS上,所以一个键不能指本地的一物体和生产中的另一物体. - 设定
contentType打开put()以确保下载时正确处理 MIME - 使用预先签名的 URL (S)
getUrl编号 :putUrl)用于直接浏览器上传/下載-并设定corsRules用于您前端的出处,或浏览器一旦部署就封存(参见 浏览器上传和下载( CORS)(中文(简体) ) - 偏爱
scan({ prefix })未覆盖scan()以限制点数成本 - 对于从 API 方法返回的浏览器上传/下载, 偏好
createUploadHandle编号 :getFileHandle超过原始的预先签名的 URL —— 它们将获取协议编码为打入的方法, 这样客户端不能滥用它们 - 使用
deleteBatch()而不是循环delete()用于大宗业务 - 版本为 默认; 非当前( 超) 版本在 90天时间 (单位:千美元)
noncurrentVersionExpirationDays默认值90),所以版本历史不会增加存储成本不受限制. 将窗口排入每个块,或禁用版本(versioned: false)随着版本化而放弃过期规则.
缩放成本( AWS)
- 计费: 按要求加存储——没有提供吞吐量
- 延迟 : 第一字节后期一般100至200毫秒
- 通过量 : 自动缩放, 每前缀有 5 500 个 GET 和 3 500 PUT 请求/ 秒
- 对象大小限制 : 5个TB每个物体
- 费用: ~0.005美元/千PUT请求,~0.04美元/千GET请求,~0.023美元/GB/月存储
- 重复性 : 99.99999999999%(11个9个)
地方发展
模拟数据持续到磁盘 .bb-data/{fullId}/ 跨 Dev 服务器重启 。 内部数据被分隔为兄弟会的根,所以它从不与你的密钥相撞:文件体活在下面 content/元数据 meta/,并在 versions/擦拭时 rm -rf .bb-dataDev 服务器在 /.bb-file-bucket/{fullId}/{path}?token=...。完全支持当地版本。 寿命周期规则和 corsRules 本地端没有效果—— dev 文件服务器接受来自任何来源的浏览器请求, 所以缺少或错误 corsRules 仅在部署后出现(参见 浏览器上传和下载( CORS)) (中文(简体) ).