Die Oberfläche ist lokalisiert; Skill-Beschreibungen und -Dokumente werden per KI automatisch in Ihre Sprache übersetzt. Code, Befehle, Pfade und Fachbegriffe bleiben im Original, maßgeblich ist das Dokument des Autors.
Skills entdecken
Daten und Forschung · SKILL.md

cloud-storage

cloud-storage

Cloud object storage integration with AWS S3, Azure Blob Storage, and Google Cloud Storage. Covers presigned URLs, multipart uploads, bucket policies, lifecycle rules, and CDN integration. USE WHEN: user mentions "S3", "blob storage", "cloud storage", "object storage", "presigned URL", "file upload to cloud", "GCS", "Azure Blob", "bucket" DO NOT USE FOR: …

Independent GitHub snapshot · Automated classification · Original documentation governs

Skill-Dokumentation

GitHub

name: cloud-storage description: | Cloud object storage integration with AWS S3, Azure Blob Storage, and Google Cloud Storage. Covers presigned URLs, multipart uploads, bucket policies, lifecycle rules, and CDN integration.

USE WHEN: user mentions "S3", "blob storage", "cloud storage", "object storage", "presigned URL", "file upload to cloud", "GCS", "Azure Blob", "bucket"

DO NOT USE FOR: local file uploads - use file-upload; database BLOB columns; local filesystem operations allowed-tools: Read, Grep, Glob, Write, Edit

Cloud Object Storage

AWS S3 (Recommended Default)

Setup (SDK v3)

import { S3Client, PutObjectCommand, GetObjectCommand } from '@aws-sdk/client-s3';
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';

const s3 = new S3Client({ region: process.env.AWS_REGION });

Upload

// Direct upload
await s3.send(new PutObjectCommand({
  Bucket: process.env.S3_BUCKET,
  Key: `uploads/${userId}/${filename}`,
  Body: buffer,
  ContentType: mimeType,
  Metadata: { 'uploaded-by': userId },
}));

// Presigned URL (client uploads directly to S3)
const url = await getSignedUrl(s3, new PutObjectCommand({
  Bucket: process.env.S3_BUCKET,
  Key: `uploads/${key}`,
  ContentType: mimeType,
}), { expiresIn: 3600 });

Presigned Download

const url = await getSignedUrl(s3, new GetObjectCommand({
  Bucket: process.env.S3_BUCKET,
  Key: fileKey,
}), { expiresIn: 3600 });

Multipart Upload (large files)

import { CreateMultipartUploadCommand, UploadPartCommand, CompleteMultipartUploadCommand } from '@aws-sdk/client-s3';
import { Upload } from '@aws-sdk/lib-storage';

// Simplified with lib-storage
const upload = new Upload({
  client: s3,
  params: { Bucket: bucket, Key: key, Body: readableStream },
  partSize: 10 * 1024 * 1024, // 10MB parts
  leavePartsOnError: false,
});
upload.on('httpUploadProgress', (progress) => console.log(progress));
await upload.done();

Python (boto3)

import boto3
from botocore.config import Config

s3 = boto3.client('s3', config=Config(signature_version='s3v4'))

# Upload
s3.upload_fileobj(file_obj, bucket, key, ExtraArgs={'ContentType': mime_type})

# Presigned URL
url = s3.generate_presigned_url('put_object',
    Params={'Bucket': bucket, 'Key': key, 'ContentType': mime_type},
    ExpiresIn=3600)

Java (Spring)

@Service
public class S3Service {
    private final S3Client s3;

    public String generatePresignedUploadUrl(String key, String contentType) {
        var presigner = S3Presigner.builder().region(Region.of(region)).build();
        var request = PutObjectPresignRequest.builder()
            .signatureDuration(Duration.ofHours(1))
            .putObjectRequest(b -> b.bucket(bucket).key(key).contentType(contentType))
            .build();
        return presigner.presignPutObject(request).url().toString();
    }
}

Bucket Policy Patterns

Public read for assets

{
  "Statement": [{
    "Effect": "Allow",
    "Principal": "*",
    "Action": "s3:GetObject",
    "Resource": "arn:aws:s3:::my-bucket/public/*"
  }]
}

CORS for direct uploads

{
  "CORSRules": [{
    "AllowedHeaders": ["*"],
    "AllowedMethods": ["PUT", "POST"],
    "AllowedOrigins": ["https://myapp.com"],
    "ExposeHeaders": ["ETag"],
    "MaxAgeSeconds": 3600
  }]
}

Anti-Patterns

Anti-PatternFix
Proxying large files through serverUse presigned URLs for direct client upload/download
No Content-Type on uploadAlways set ContentType to enable correct browser behavior
Predictable file keysUse UUIDs or hashed paths to prevent enumeration
No lifecycle rulesSet expiration for temp uploads, transition old files to Glacier
Long-lived presigned URLsKeep expiry short (1h for uploads, 15m for downloads)
No multipart for large filesUse multipart upload for files > 100MB

Quick Troubleshooting

IssueCauseFix
403 on presigned URLExpired, wrong region, or CORSCheck expiry, region, CORS config
SignatureDoesNotMatchContentType mismatchEnsure client sends same ContentType used in signing
Slow uploadsSingle-part for large filesUse multipart upload with parallel parts
CORS errorsMissing CORS configurationAdd CORSRules to bucket
AccessDenied on public filesMissing bucket policyAdd public read policy for the prefix

Production Checklist

  • Presigned URLs for all client uploads (never proxy large files)
  • ContentType set on every upload
  • UUID-based keys (prevent enumeration)
  • CORS configured for direct uploads
  • Lifecycle rules for temp/old files
  • Encryption at rest enabled (SSE-S3 or SSE-KMS)
  • Access logging enabled
  • Versioning enabled for critical buckets
  • CloudFront CDN for public assets
Gespeicherte Skills