Object storage integration
Encapsulates storage-provider differences behind a practical adapter while preserving streaming, signing and browser-upload requirements.
object-storage-integration
See how it helpsWhen is it useful?
Use it when adding cloud or local object storage without spreading provider SDK details through application logic.
What does it help you do?
- Defines streaming, metadata, signing and copy adapter operations.
- Checks provider-specific behavior instead of assuming S3 equivalence.
- Configures exact browser origins and exposed multipart ETag headers.
Try asking this
Integrate private uploads with R2 while preserving checksums and browser multipart completion. Upload multiple browser parts, complete the object and verify its checksum. Test a disallowed origin and an expired signed request without making the object public.
Detailed documentation
Read the skill’s original instructions, examples and checks in their authored language.
Show less
Object Storage Integration
While AWS S3, Cloudflare R2, MinIO, Backblaze B2, DigitalOcean Spaces, Google Cloud Storage, Azure Blob Storage and local disk all store byte blobs by key, their consistency guarantees, presigned URL capabilities, CORS rules, checksum headers and metadata limits differ. Hide vendor mechanics behind a narrow storage port while respecting provider-specific constraints.
1. Designing the Storage Adapter Boundary
Define a clean internal interface for storage operations without leaking SDK types into business services:
putStream(key, readableStream, { contentType, contentLength, sha256, metadata })getStream(key, { range }) -> { stream, contentLength, contentType, etag }head(key) -> { exists, sizeBytes, contentType, etag, checksum, lastModified }createPresignedUpload(key, { contentType, contentLengthRange, expiresInSeconds, checksumSha256 })createPresignedDownload(key, { expiresInSeconds, responseContentDisposition, responseContentType })delete(key)(idempotent — succeeds when object is already absent)copy(sourceKey, destKey)
2. Provider-Specific Capabilities & Gotchas
- AWS S3:
- Block Public Access (
BlockPublicAcls,IgnorePublicAcls,BlockPublicPolicy,RestrictPublicBuckets) must be enabled on private buckets. - Supports both presigned
PUT(exact headers bound into signature) and presignedPOST(supports["content-length-range", min, max]policy conditions!).
- Block Public Access (
- Cloudflare R2 / MinIO / S3-Compatible Stores:
- Verify whether
createPresignedPostis supported by the target provider (some S3-compatible providers only support presignedPUT+Content-Lengthbinding). - Set
region: 'auto'(for R2) orforcePathStyle: true(for local MinIO / custom endpoints) in@aws-sdk/client-s3.
- Verify whether
- Azure Blob Storage:
- Uses Block Blobs (
StageBlock->CommitBlockListfor chunked uploads) and SAS (Shared Access Signature) tokens (BlobSASPermissions:r,w,c,dscoped to exact blob path, start/expiry time andhttpsprotocol).
- Uses Block Blobs (
- Local Filesystem (Development / Self-Hosted Single-Node):
- Write uploads to a temporary file on the same filesystem mount as the target directory, then
fs.rename()atomically into place once the stream and checksum succeed so readers never observe a half-written file. - Shard directories by prefix (
blobs/ab/cd/abcdef...) so a single folder never accumulates millions of inodes.
- Write uploads to a temporary file on the same filesystem mount as the target directory, then
3. Browser CORS & Checksum Headers
Direct browser-to-object-store uploads fail silently if bucket CORS is misconfigured:
- Allow only the application's exact origins (
AllowedOrigins), methods (PUT,POST,GET,HEAD), and required headers (Content-Type,Content-MD5,x-amz-checksum-sha256,x-ms-blob-type). - Expose
ETaginExposeHeaders(Access-Control-Allow-Headers/Access-Control-Expose-Headers: ETag) — without it, browser JavaScript cannot read theETagresponse header required to complete S3 Multipart uploads!
Included files 1
SKILL.md
