服务器 存储:S3、GCS、Azure 与磁盘
存储:S3、GCS、Azure 与磁盘
本页内容
密钥
在 Cloudflare R2 中:R2 → Create bucket,然后 Manage API tokens → Create API token,仅为该存储桶授予 “Object Read & Write”。
# The S3 API of the account, not the public address of the bucket (r2.dev)
S3_ENDPOINT=https://<account-id>.r2.cloudflarestorage.com
S3_BUCKET=acme-files
S3_REGION=auto
S3_ACCESS_KEY_ID=…
S3_SECRET_ACCESS_KEY=…
# Optional: before every key, to share the bucket with something else
S3_PREFIX=files/
# What tokens are signed with: long, random, the same in every process
REBOFILES_SECRET=…s3Storage(s3OptionsFrom(process.env)) 会读取它们。在 AWS 上,省略 S3_ENDPOINT 并提供区域;MinIO 和 Backblaze 使用相同的变量。
跨域规则
在 Settings → CORS policy 中,填入你的应用所在的地址。必须暴露 ETag。
[
{
"AllowedOrigins": ["https://your-app.com", "http://localhost:3000"],
"AllowedMethods": ["GET", "PUT"],
"AllowedHeaders": ["content-type"],
"ExposeHeaders": ["ETag"],
"MaxAgeSeconds": 3600
}
]再加一条生命周期规则,在一天后中止未完成的分片上传,就能避免从未完成的上传分片一直留在存储桶中。
Google Cloud Storage
通过兼容 S3 的 XML API:同样的地址,用存储桶的 HMAC 密钥签名。
import { gcsOptionsFrom, gcsStorage } from '@rebofiles/server';
// An HMAC key of the bucket: Cloud Storage → Settings → Interoperability.
// GCS_BUCKET, GCS_ACCESS_KEY_ID (GOOG1…), GCS_SECRET_ACCESS_KEY, GCS_PREFIX
createDriveHandler({ ...options, storage: gcsStorage(gcsOptionsFrom(process.env)) });该 API 不支持的操作换一种方式完成:逐个删除对象;新版本的所有分片都会上传,因为它不支持复制分片。存储桶的 CORS(用 gcloud storage buckets update --cors-file 设置)必须公开 ETag。
Azure Blob Storage
存储帐户中的一个容器:地址用帐户密钥签名(每个 blob 的 SAS,有效几分钟),每个分片是一个块,文件由块列表组成。
import { azureOptionsFrom, azureStorage } from '@rebofiles/server';
// AZURE_STORAGE_ACCOUNT, AZURE_STORAGE_KEY, AZURE_STORAGE_CONTAINER, AZURE_STORAGE_PREFIX
createDriveHandler({ ...options, storage: azureStorage(azureOptionsFrom(process.env)) });- 根据 Azure 列出的块继续中断的上传;新版本只上传变化的分片(Put Block From URL)。
- 从未完成的上传留下的块会在一周后自动清除:无需清理。
- 帐户的 CORS(资源共享)需允许你的页面来源,并允许
PUT、GET和HEAD;无需公开任何响应头,因为块按编号组合。 - 已在服务器的测试中用微软的模拟器 Azurite 验证。
存放在磁盘上
diskStorage({ folder, secret }) 把文件内容保存在一个文件夹中,由服务器自己通过它的地址传输:适用于单机、演示或测试。
出现问题时
S3_ENDPOINT is the public address of the bucket (r2.dev)
R2 的 S3 API 位于 https://<account-id>.r2.cloudflarestorage.com,可在存储桶的设置页面找到。
The part could not be sent. If the bytes go to a bucket, check that it lets this origin in.
跨域规则问题:AllowedOrigins 中缺少页面地址,或 AllowedHeaders 中缺少 content-type。
The bucket did not let the page read the ETag of a part.
小文件能上传而大文件不能:ExposeHeaders 需要包含 ETag。
The bucket answered 403 to …
密钥问题:它无权写入该存储桶,或者 endpoint、区域或存储桶名称与创建密钥时的不一致。
There is no room for it: … are used, and it is ….
该用户的配额已满(413 over-quota):在网盘设置中增加空间,或减少其文件和回收站中的内容。
在仓库中,npm run storage:check 会针对 apps/storage/.env 中的存储桶走一遍文件的完整流程,并告诉你出错那一步存储桶返回了什么。