or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

access-control-security.mdbucket-configuration.mdbucket-operations.mdclient-configuration.mdindex.mdlisting-pagination.mdmultipart-upload.mdobject-operations.mdwaiters-utilities.md
tile.json

object-operations.mddocs/

Object Operations

Core object storage operations for uploading, downloading, copying, and managing S3 objects with comprehensive metadata and configuration support.

Capabilities

Upload Objects

Upload objects to S3 with support for metadata, storage classes, and server-side encryption.

/**
 * Upload an object to S3
 */
class PutObjectCommand {
  constructor(input: PutObjectCommandInput);
}

interface PutObjectCommandInput {
  /** Target bucket name */
  Bucket: string;
  
  /** Object key (path/filename) */
  Key: string;
  
  /** Object content (string, Buffer, Stream, etc.) */
  Body?: StreamingBlobPayloadInputTypes;
  
  /** Object permissions */
  ACL?: ObjectCannedACL;
  
  /** Cache control header */
  CacheControl?: string;
  
  /** Content disposition header */
  ContentDisposition?: string;
  
  /** Content encoding header */
  ContentEncoding?: string;
  
  /** Content language header */
  ContentLanguage?: string;
  
  /** Content length in bytes */
  ContentLength?: number;
  
  /** MD5 hash of the content */
  ContentMD5?: string;
  
  /** MIME type of the content */
  ContentType?: string;
  
  /** Object expiration date */
  Expires?: Date;
  
  /** User-defined metadata */
  Metadata?: Record<string, string>;
  
  /** Server-side encryption algorithm */
  ServerSideEncryption?: ServerSideEncryption;
  
  /** KMS key ID for encryption */
  SSEKMSKeyId?: string;
  
  /** Storage class for the object */
  StorageClass?: StorageClass;
  
  /** Object tagging */
  Tagging?: string;
  
  /** Website redirect location */
  WebsiteRedirectLocation?: string;
  
  /** Request payer setting */
  RequestPayer?: RequestPayer;
  
  /** Object lock mode */
  ObjectLockMode?: ObjectLockMode;
  
  /** Object lock retain until date */
  ObjectLockRetainUntilDate?: Date;
  
  /** Object lock legal hold status */
  ObjectLockLegalHoldStatus?: ObjectLockLegalHoldStatus;
  
  /** Checksum algorithm */
  ChecksumAlgorithm?: ChecksumAlgorithm;
  
  /** Expected bucket owner */
  ExpectedBucketOwner?: string;
}

interface PutObjectCommandOutput {
  /** ETag of the uploaded object */
  ETag?: string;
  
  /** Server-side encryption algorithm used */
  ServerSideEncryption?: ServerSideEncryption;
  
  /** Version ID of the object (if versioning enabled) */
  VersionId?: string;
  
  /** KMS key ID used for encryption */
  SSEKMSKeyId?: string;
  
  /** Request charged information */
  RequestCharged?: RequestCharged;
  
  /** Checksum values */
  ChecksumCRC32?: string;
  ChecksumCRC32C?: string;
  ChecksumSHA1?: string;
  ChecksumSHA256?: string;
}

Usage Examples:

import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";
import { readFileSync } from "fs";

const client = new S3Client({ region: "us-east-1" });

// Upload text content
const textUpload = new PutObjectCommand({
  Bucket: "my-bucket",
  Key: "documents/readme.txt",
  Body: "Hello, S3!",
  ContentType: "text/plain",
  Metadata: {
    author: "John Doe",
    category: "documentation"
  }
});
await client.send(textUpload);

// Upload file with encryption
const fileUpload = new PutObjectCommand({
  Bucket: "secure-bucket", 
  Key: "sensitive/data.json",
  Body: readFileSync("./data.json"),
  ContentType: "application/json",
  ServerSideEncryption: "aws:kms",
  SSEKMSKeyId: "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012",
  StorageClass: "STANDARD_IA"
});
await client.send(fileUpload);

// Upload with storage class and tagging
const archiveUpload = new PutObjectCommand({
  Bucket: "archive-bucket",
  Key: "backups/backup-2024.zip", 
  Body: readFileSync("./backup.zip"),
  StorageClass: "GLACIER",
  Tagging: "type=backup&year=2024&retention=7years"
});
await client.send(archiveUpload);

Download Objects

Download objects from S3 with support for range requests and conditional downloads.

/**
 * Download an object from S3
 */
class GetObjectCommand {
  constructor(input: GetObjectCommandInput);
}

interface GetObjectCommandInput {
  /** Source bucket name */
  Bucket: string;
  
  /** Object key to download */
  Key: string;
  
  /** Return only if modified since date */
  IfModifiedSince?: Date;
  
  /** Return only if not modified since date */
  IfUnmodifiedSince?: Date;
  
  /** Return only if ETag matches */
  IfMatch?: string;
  
  /** Return only if ETag doesn't match */
  IfNoneMatch?: string;
  
  /** Byte range to download (e.g., "bytes=0-1023") */
  Range?: string;
  
  /** Override response cache control */
  ResponseCacheControl?: string;
  
  /** Override response content disposition */
  ResponseContentDisposition?: string;
  
  /** Override response content encoding */
  ResponseContentEncoding?: string;
  
  /** Override response content language */
  ResponseContentLanguage?: string;
  
  /** Override response content type */
  ResponseContentType?: string;
  
  /** Override response expires header */
  ResponseExpires?: Date;
  
  /** Version ID to download (if versioning enabled) */
  VersionId?: string;
  
  /** SSE customer algorithm */
  SSECustomerAlgorithm?: string;
  
  /** SSE customer key */
  SSECustomerKey?: string;
  
  /** SSE customer key MD5 */
  SSECustomerKeyMD5?: string;
  
  /** Request payer setting */
  RequestPayer?: RequestPayer;
  
  /** Part number for multipart object */
  PartNumber?: number;
  
  /** Expected bucket owner */
  ExpectedBucketOwner?: string;
  
  /** Checksum mode */
  ChecksumMode?: ChecksumMode;
}

interface GetObjectCommandOutput {
  /** Object content stream */
  Body?: StreamingBlobPayloadOutputTypes;
  
  /** Delete marker flag */
  DeleteMarker?: boolean;
  
  /** Object expiration info */
  Expiration?: string;
  
  /** Restore status for archived objects */
  Restore?: string;
  
  /** Last modified date */
  LastModified?: Date;
  
  /** Content length in bytes */
  ContentLength?: number;
  
  /** ETag of the object */
  ETag?: string;
  
  /** Checksum values */
  ChecksumCRC32?: string;
  ChecksumCRC32C?: string;
  ChecksumSHA1?: string;
  ChecksumSHA256?: string;
  
  /** Number of parts (for multipart objects) */
  PartsCount?: number;
  
  /** Object tags count */
  TagCount?: number;
  
  /** Version ID */
  VersionId?: string;
  
  /** Cache control header */
  CacheControl?: string;
  
  /** Content disposition header */
  ContentDisposition?: string;
  
  /** Content encoding header */
  ContentEncoding?: string;
  
  /** Content language header */
  ContentLanguage?: string;
  
  /** Content type header */
  ContentType?: string;
  
  /** Expiration header */
  Expires?: Date;
  
  /** User-defined metadata */
  Metadata?: Record<string, string>;
  
  /** Storage class */
  StorageClass?: StorageClass;
  
  /** Server-side encryption info */
  ServerSideEncryption?: ServerSideEncryption;
  SSEKMSKeyId?: string;
}

Usage Examples:

import { S3Client, GetObjectCommand } from "@aws-sdk/client-s3";
import { writeFileSync } from "fs";

const client = new S3Client({ region: "us-east-1" });

// Download complete object
const download = new GetObjectCommand({
  Bucket: "my-bucket",
  Key: "documents/readme.txt"
});
const response = await client.send(download);
const content = await response.Body?.transformToString();
console.log(content);

// Download with range request (first 1KB)
const partialDownload = new GetObjectCommand({
  Bucket: "my-bucket",
  Key: "large-file.zip",
  Range: "bytes=0-1023"
});
const partialResponse = await client.send(partialDownload);

// Download specific version
const versionDownload = new GetObjectCommand({
  Bucket: "versioned-bucket",
  Key: "document.pdf",
  VersionId: "3/L4kqtJlcpXroDTDmpUMLUo"
});
const versionResponse = await client.send(versionDownload);

// Conditional download (only if modified)
const conditionalDownload = new GetObjectCommand({
  Bucket: "my-bucket",
  Key: "data.json",
  IfModifiedSince: new Date("2024-01-01")
});
const conditionalResponse = await client.send(conditionalDownload);

Copy Objects

Copy objects within S3 or between buckets with metadata preservation or modification.

/**
 * Copy an object within S3
 */
class CopyObjectCommand {
  constructor(input: CopyObjectCommandInput);
}

interface CopyObjectCommandInput {
  /** Destination bucket name */
  Bucket: string;
  
  /** Source object specification (bucket/key) */
  CopySource: string;
  
  /** Destination object key */
  Key: string;
  
  /** Destination object permissions */
  ACL?: ObjectCannedACL;
  
  /** Cache control for destination */
  CacheControl?: string;
  
  /** Content disposition for destination */
  ContentDisposition?: string;
  
  /** Content encoding for destination */
  ContentEncoding?: string;
  
  /** Content language for destination */
  ContentLanguage?: string;
  
  /** Content type for destination */
  ContentType?: string;
  
  /** Copy source if modified since */
  CopySourceIfModifiedSince?: Date;
  
  /** Copy source if unmodified since */
  CopySourceIfUnmodifiedSince?: Date;
  
  /** Copy source if ETag matches */
  CopySourceIfMatch?: string;
  
  /** Copy source if ETag doesn't match */
  CopySourceIfNoneMatch?: string;
  
  /** Expiration date for destination */
  Expires?: Date;
  
  /** Metadata directive (COPY or REPLACE) */
  MetadataDirective?: MetadataDirective;
  
  /** New metadata for destination */
  Metadata?: Record<string, string>;
  
  /** Server-side encryption for destination */
  ServerSideEncryption?: ServerSideEncryption;
  
  /** Storage class for destination */
  StorageClass?: StorageClass;
  
  /** Website redirect location */
  WebsiteRedirectLocation?: string;
  
  /** KMS key for destination encryption */
  SSEKMSKeyId?: string;
  
  /** Source version ID */
  CopySourceVersionId?: string;
  
  /** Object tagging directive */
  TaggingDirective?: TaggingDirective;
  
  /** Tags for destination object */
  Tagging?: string;
}

interface CopyObjectCommandOutput {
  /** Copy result information */
  CopyObjectResult?: CopyObjectResult;
  
  /** Expiration info */
  Expiration?: string;
  
  /** Version ID of destination */
  VersionId?: string;
  
  /** Server-side encryption used */
  ServerSideEncryption?: ServerSideEncryption;
  
  /** KMS key ID used */
  SSEKMSKeyId?: string;
  
  /** Request charged information */
  RequestCharged?: RequestCharged;
}

interface CopyObjectResult {
  /** ETag of copied object */
  ETag?: string;
  
  /** Last modified date */
  LastModified?: Date;
  
  /** Checksum values */
  ChecksumCRC32?: string;
  ChecksumCRC32C?: string;
  ChecksumSHA1?: string;
  ChecksumSHA256?: string;
}

Usage Examples:

import { S3Client, CopyObjectCommand } from "@aws-sdk/client-s3";

const client = new S3Client({ region: "us-east-1" });

// Simple copy within same bucket
const simpleCopy = new CopyObjectCommand({
  Bucket: "my-bucket",
  CopySource: "my-bucket/original/file.txt",
  Key: "backup/file.txt"
});
await client.send(simpleCopy);

// Copy between buckets with new metadata
const crossBucketCopy = new CopyObjectCommand({
  Bucket: "destination-bucket",
  CopySource: "source-bucket/data/report.pdf",
  Key: "reports/monthly-report.pdf",
  MetadataDirective: "REPLACE",
  Metadata: {
    "copied-date": new Date().toISOString(),
    "original-bucket": "source-bucket"
  },
  StorageClass: "STANDARD_IA"
});
await client.send(crossBucketCopy);

// Conditional copy with encryption
const encryptedCopy = new CopyObjectCommand({
  Bucket: "secure-bucket",
  CopySource: "temp-bucket/upload.doc",
  Key: "documents/secure-doc.doc",
  CopySourceIfModifiedSince: new Date("2024-01-01"),
  ServerSideEncryption: "aws:kms",
  SSEKMSKeyId: "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012"
});
await client.send(encryptedCopy);

Delete Objects

Delete single or multiple objects from S3 with support for versioned buckets.

/**
 * Delete a single object
 */
class DeleteObjectCommand {
  constructor(input: DeleteObjectCommandInput);
}

interface DeleteObjectCommandInput {
  /** Target bucket name */
  Bucket: string;
  
  /** Object key to delete */
  Key: string;
  
  /** Multi-factor authentication token */
  MFA?: string;
  
  /** Version ID to delete (for versioned buckets) */
  VersionId?: string;
  
  /** Request payer setting */
  RequestPayer?: RequestPayer;
  
  /** Bypass governance mode retention */
  BypassGovernanceRetention?: boolean;
  
  /** Expected bucket owner */
  ExpectedBucketOwner?: string;
}

interface DeleteObjectCommandOutput {
  /** Delete marker created */
  DeleteMarker?: boolean;
  
  /** Version ID deleted */
  VersionId?: string;
  
  /** Request charged information */
  RequestCharged?: RequestCharged;
}

/**
 * Delete multiple objects in a single request
 */
class DeleteObjectsCommand {
  constructor(input: DeleteObjectsCommandInput);
}

interface DeleteObjectsCommandInput {
  /** Target bucket name */
  Bucket: string;
  
  /** Objects to delete specification */
  Delete: Delete;
  
  /** Multi-factor authentication token */
  MFA?: string;
  
  /** Request payer setting */
  RequestPayer?: RequestPayer;
  
  /** Bypass governance mode retention */
  BypassGovernanceRetention?: boolean;
  
  /** Expected bucket owner */
  ExpectedBucketOwner?: string;
  
  /** Checksum algorithm */
  ChecksumAlgorithm?: ChecksumAlgorithm;
}

interface Delete {
  /** List of objects to delete */
  Objects: ObjectIdentifier[];
  
  /** Return detailed results for each object */
  Quiet?: boolean;
}

interface ObjectIdentifier {
  /** Object key */
  Key: string;
  
  /** Version ID (for versioned buckets) */
  VersionId?: string;
}

interface DeleteObjectsCommandOutput {
  /** Successfully deleted objects */
  Deleted?: DeletedObject[];
  
  /** Objects that couldn't be deleted */
  Errors?: Error[];
  
  /** Request charged information */
  RequestCharged?: RequestCharged;
}

Usage Examples:

import { S3Client, DeleteObjectCommand, DeleteObjectsCommand } from "@aws-sdk/client-s3";

const client = new S3Client({ region: "us-east-1" });

// Delete single object
const singleDelete = new DeleteObjectCommand({
  Bucket: "my-bucket",
  Key: "temp/file-to-delete.txt"
});
await client.send(singleDelete);

// Delete specific version
const versionDelete = new DeleteObjectCommand({
  Bucket: "versioned-bucket",
  Key: "document.pdf",
  VersionId: "3/L4kqtJlcpXroDTDmpUMLUo"
});
await client.send(versionDelete);

// Delete multiple objects
const bulkDelete = new DeleteObjectsCommand({
  Bucket: "cleanup-bucket",
  Delete: {
    Objects: [
      { Key: "temp/file1.txt" },
      { Key: "temp/file2.txt" },
      { Key: "old/archive.zip" }
    ],
    Quiet: false
  }
});
const deleteResult = await client.send(bulkDelete);
console.log(`Deleted ${deleteResult.Deleted?.length} objects`);

Object Metadata

Retrieve object metadata without downloading the content.

/**
 * Get object metadata without downloading content
 */
class HeadObjectCommand {
  constructor(input: HeadObjectCommandInput);
}

interface HeadObjectCommandInput {
  /** Source bucket name */
  Bucket: string;
  
  /** Object key */
  Key: string;
  
  /** Return only if modified since */
  IfModifiedSince?: Date;
  
  /** Return only if unmodified since */
  IfUnmodifiedSince?: Date;
  
  /** Return only if ETag matches */
  IfMatch?: string;
  
  /** Return only if ETag doesn't match */
  IfNoneMatch?: string;
  
  /** Range for partial metadata */
  Range?: string;
  
  /** Version ID */
  VersionId?: string;
  
  /** SSE customer algorithm */
  SSECustomerAlgorithm?: string;
  
  /** SSE customer key */
  SSECustomerKey?: string;
  
  /** SSE customer key MD5 */
  SSECustomerKeyMD5?: string;
  
  /** Request payer setting */
  RequestPayer?: RequestPayer;
  
  /** Part number */
  PartNumber?: number;
  
  /** Expected bucket owner */
  ExpectedBucketOwner?: string;
  
  /** Checksum mode */
  ChecksumMode?: ChecksumMode;
}

interface HeadObjectCommandOutput {
  /** Delete marker flag */
  DeleteMarker?: boolean;
  
  /** Accept ranges header */
  AcceptRanges?: string;
  
  /** Expiration info */
  Expiration?: string;
  
  /** Restore status */
  Restore?: string;
  
  /** Archive status */
  ArchiveStatus?: ArchiveStatus;
  
  /** Last modified date */
  LastModified?: Date;
  
  /** Content length */
  ContentLength?: number;
  
  /** ETag */
  ETag?: string;
  
  /** Checksum values */
  ChecksumCRC32?: string;
  ChecksumCRC32C?: string;
  ChecksumSHA1?: string;
  ChecksumSHA256?: string;
  
  /** Parts count */
  PartsCount?: number;
  
  /** Tag count */
  TagCount?: number;
  
  /** Version ID */
  VersionId?: string;
  
  /** Content headers */
  CacheControl?: string;
  ContentDisposition?: string;
  ContentEncoding?: string;
  ContentLanguage?: string;
  ContentType?: string;
  Expires?: Date;
  
  /** User metadata */
  Metadata?: Record<string, string>;
  
  /** Storage class */
  StorageClass?: StorageClass;
  
  /** Encryption info */
  ServerSideEncryption?: ServerSideEncryption;
  SSEKMSKeyId?: string;
  
  /** Website redirect location */
  WebsiteRedirectLocation?: string;
  
  /** Object lock info */
  ObjectLockMode?: ObjectLockMode;
  ObjectLockRetainUntilDate?: Date;
  ObjectLockLegalHoldStatus?: ObjectLockLegalHoldStatus;
}

Usage Example:

import { S3Client, HeadObjectCommand } from "@aws-sdk/client-s3";

const client = new S3Client({ region: "us-east-1" });

const headObject = new HeadObjectCommand({
  Bucket: "my-bucket",
  Key: "documents/report.pdf"
});

const metadata = await client.send(headObject);
console.log(`File size: ${metadata.ContentLength} bytes`);
console.log(`Last modified: ${metadata.LastModified}`);
console.log(`Content type: ${metadata.ContentType}`);
console.log(`User metadata:`, metadata.Metadata);

Object Tagging

Manage tags on S3 objects for cost allocation, access control, and resource management.

/**
 * Get the tag-set of an object
 */
class GetObjectTaggingCommand {
  constructor(input: GetObjectTaggingCommandInput);
}

interface GetObjectTaggingCommandInput {
  /** Bucket name containing the object */
  Bucket: string;
  
  /** Object key */
  Key: string;
  
  /** Version ID of the object */
  VersionId?: string;
  
  /** Expected bucket owner */
  ExpectedBucketOwner?: string;
  
  /** Request payer setting */
  RequestPayer?: RequestPayer;
}

interface GetObjectTaggingCommandOutput {
  /** Version ID of the object */
  VersionId?: string;
  
  /** Tag set */
  TagSet: Tag[];
}

/**
 * Set the tag-set for an object
 */
class PutObjectTaggingCommand {
  constructor(input: PutObjectTaggingCommandInput);
}

interface PutObjectTaggingCommandInput {
  /** Bucket name containing the object */
  Bucket: string;
  
  /** Object key */
  Key: string;
  
  /** Version ID of the object */
  VersionId?: string;
  
  /** MD5 hash of the content */
  ContentMD5?: string;
  
  /** Checksum algorithm */
  ChecksumAlgorithm?: ChecksumAlgorithm;
  
  /** Tag set */
  Tagging: Tagging;
  
  /** Expected bucket owner */
  ExpectedBucketOwner?: string;
  
  /** Request payer setting */
  RequestPayer?: RequestPayer;
}

interface PutObjectTaggingCommandOutput {
  /** Version ID of the object */
  VersionId?: string;
}

/**
 * Remove the tag-set from an object
 */
class DeleteObjectTaggingCommand {
  constructor(input: DeleteObjectTaggingCommandInput);
}

interface DeleteObjectTaggingCommandInput {
  /** Bucket name containing the object */
  Bucket: string;
  
  /** Object key */
  Key: string;
  
  /** Version ID of the object */
  VersionId?: string;
  
  /** Expected bucket owner */
  ExpectedBucketOwner?: string;
}

interface DeleteObjectTaggingCommandOutput {
  /** Version ID of the object */
  VersionId?: string;
}

// Tagging-related types
interface Tag {
  /** Tag name */
  Key: string;
  
  /** Tag value */
  Value: string;
}

interface Tagging {
  /** Collection of tags */
  TagSet: Tag[];
}

Usage Examples:

import { 
  S3Client, 
  GetObjectTaggingCommand,
  PutObjectTaggingCommand,
  DeleteObjectTaggingCommand
} from "@aws-sdk/client-s3";

const client = new S3Client({ region: "us-east-1" });

// Get object tags
async function getObjectTags(bucket: string, key: string) {
  const command = new GetObjectTaggingCommand({
    Bucket: bucket,
    Key: key
  });
  
  const response = await client.send(command);
  console.log("Object tags:", response.TagSet);
  return response.TagSet;
}

// Set object tags
async function setObjectTags(bucket: string, key: string, tags: Record<string, string>) {
  const tagSet = Object.entries(tags).map(([Key, Value]) => ({ Key, Value }));
  
  const command = new PutObjectTaggingCommand({
    Bucket: bucket,
    Key: key,
    Tagging: {
      TagSet: tagSet
    }
  });
  
  const response = await client.send(command);
  console.log(`Tags set for ${key}:`, tagSet);
  return response;
}

// Remove all tags from an object
async function removeObjectTags(bucket: string, key: string) {
  const command = new DeleteObjectTaggingCommand({
    Bucket: bucket,
    Key: key
  });
  
  const response = await client.send(command);
  console.log(`All tags removed from ${key}`);
  return response;
}

// Add/update specific tags while preserving others
async function updateObjectTags(
  bucket: string, 
  key: string, 
  newTags: Record<string, string>
) {
  try {
    // Get existing tags
    const existingTags = await getObjectTags(bucket, key);
    
    // Convert to map for easier manipulation
    const tagMap = new Map<string, string>();
    existingTags.forEach(tag => tagMap.set(tag.Key, tag.Value));
    
    // Add/update new tags
    Object.entries(newTags).forEach(([key, value]) => {
      tagMap.set(key, value);
    });
    
    // Convert back to tag array and set
    const updatedTags = Object.fromEntries(tagMap);
    return await setObjectTags(bucket, key, updatedTags);
    
  } catch (error) {
    if (error instanceof Error && error.name === "NoSuchTagSet") {
      // No existing tags, just set the new ones
      return await setObjectTags(bucket, key, newTags);
    }
    throw error;
  }
}

// Remove specific tags while preserving others
async function removeSpecificTags(
  bucket: string, 
  key: string, 
  tagsToRemove: string[]
) {
  try {
    // Get existing tags
    const existingTags = await getObjectTags(bucket, key);
    
    // Filter out tags to remove
    const remainingTags = existingTags.filter(
      tag => !tagsToRemove.includes(tag.Key)
    );
    
    if (remainingTags.length === 0) {
      // Remove all tags
      return await removeObjectTags(bucket, key);
    } else {
      // Set the remaining tags
      const tagMap = Object.fromEntries(
        remainingTags.map(tag => [tag.Key, tag.Value])
      );
      return await setObjectTags(bucket, key, tagMap);
    }
    
  } catch (error) {
    if (error instanceof Error && error.name === "NoSuchTagSet") {
      console.log("Object has no tags to remove");
      return;
    }
    throw error;
  }
}

// Example usage
async function tagManagementExample() {
  const bucket = "my-bucket";
  const key = "documents/report.pdf";
  
  // Set initial tags
  await setObjectTags(bucket, key, {
    "Environment": "production",
    "Department": "Finance",
    "CostCenter": "12345"
  });
  
  // Add additional tags
  await updateObjectTags(bucket, key, {
    "Project": "Q4-Report",
    "Owner": "alice@company.com"
  });
  
  // Remove specific tags
  await removeSpecificTags(bucket, key, ["CostCenter"]);
  
  // Get final tag set
  const finalTags = await getObjectTags(bucket, key);
  console.log("Final tags:", finalTags);
}

Object Attributes

Retrieve detailed object metadata and attributes without downloading the content.

/**
 * Get detailed object attributes and metadata
 */
class GetObjectAttributesCommand {
  constructor(input: GetObjectAttributesCommandInput);
}

interface GetObjectAttributesCommandInput {
  /** Bucket name containing the object */
  Bucket: string;
  
  /** Object key */
  Key: string;
  
  /** Version ID of the object */
  VersionId?: string;
  
  /** Maximum number of parts to return */
  MaxParts?: number;
  
  /** Part number marker for pagination */
  PartNumberMarker?: string;
  
  /** SSE customer algorithm */
  SSECustomerAlgorithm?: string;
  
  /** SSE customer key */
  SSECustomerKey?: string;
  
  /** SSE customer key MD5 */
  SSECustomerKeyMD5?: string;
  
  /** Request payer setting */
  RequestPayer?: RequestPayer;
  
  /** Expected bucket owner */
  ExpectedBucketOwner?: string;
  
  /** Object attributes to retrieve */
  ObjectAttributes: ObjectAttributes[];
}

interface GetObjectAttributesCommandOutput {
  /** Delete marker flag */
  DeleteMarker?: boolean;
  
  /** Last modified date */
  LastModified?: Date;
  
  /** Version ID */
  VersionId?: string;
  
  /** Request charged */
  RequestCharged?: RequestCharged;
  
  /** ETag */
  ETag?: string;
  
  /** Checksum details */
  Checksum?: Checksum;
  
  /** Object parts information */
  ObjectParts?: GetObjectAttributesParts;
  
  /** Storage class */
  StorageClass?: StorageClass;
  
  /** Object size */
  ObjectSize?: number;
}

type ObjectAttributes = 
  | "ETag"
  | "Checksum" 
  | "ObjectParts"
  | "StorageClass"
  | "ObjectSize";

interface GetObjectAttributesParts {
  /** Whether more parts exist */
  IsTruncated?: boolean;
  
  /** Maximum parts returned */
  MaxParts?: number;
  
  /** Next part number marker */
  NextPartNumberMarker?: string;
  
  /** Part number marker */
  PartNumberMarker?: string;
  
  /** Array of object parts */
  Parts?: ObjectPart[];
  
  /** Total parts count */
  PartsCount?: number;
}

interface ObjectPart {
  /** Part number */
  PartNumber?: number;
  
  /** Part size */
  Size?: number;
  
  /** Checksum CRC32 */
  ChecksumCRC32?: string;
  
  /** Checksum CRC32C */
  ChecksumCRC32C?: string;
  
  /** Checksum SHA1 */
  ChecksumSHA1?: string;
  
  /** Checksum SHA256 */
  ChecksumSHA256?: string;
}

interface Checksum {
  /** Checksum CRC32 */
  ChecksumCRC32?: string;
  
  /** Checksum CRC32C */
  ChecksumCRC32C?: string;
  
  /** Checksum SHA1 */
  ChecksumSHA1?: string;
  
  /** Checksum SHA256 */
  ChecksumSHA256?: string;
}

Usage Example:

import { S3Client, GetObjectAttributesCommand } from "@aws-sdk/client-s3";

const client = new S3Client({ region: "us-east-1" });

async function getObjectDetails(bucket: string, key: string) {
  const command = new GetObjectAttributesCommand({
    Bucket: bucket,
    Key: key,
    ObjectAttributes: ["ETag", "ObjectSize", "StorageClass", "Checksum"]
  });
  
  const response = await client.send(command);
  console.log(`Object: ${key}`);
  console.log(`Size: ${response.ObjectSize} bytes`);
  console.log(`ETag: ${response.ETag}`);
  console.log(`Storage Class: ${response.StorageClass}`);
  console.log(`Last Modified: ${response.LastModified}`);
  
  if (response.Checksum) {
    console.log("Checksums:", response.Checksum);
  }
  
  return response;
}

// Get multipart object details
async function getMultipartObjectParts(bucket: string, key: string) {
  const command = new GetObjectAttributesCommand({
    Bucket: bucket,
    Key: key,
    ObjectAttributes: ["ObjectParts"],
    MaxParts: 1000
  });
  
  const response = await client.send(command);
  
  if (response.ObjectParts) {
    console.log(`Total parts: ${response.ObjectParts.PartsCount}`);
    console.log(`Parts returned: ${response.ObjectParts.Parts?.length}`);
    
    response.ObjectParts.Parts?.forEach((part, index) => {
      console.log(`Part ${part.PartNumber}: ${part.Size} bytes`);
    });
  }
  
  return response;
}

Error Handling

Comprehensive error handling patterns for S3 operations with specific exception types and retry strategies.

// Base S3 exception class
class S3ServiceException extends Error {
  name: string;
  $fault: "client" | "server";
  $metadata: ResponseMetadata;
  $retryable?: RetryableTrait;
}

// Common S3 error types
interface ResponseMetadata {
  httpStatusCode?: number;
  requestId?: string;
  extendedRequestId?: string;
  cfId?: string;
  attempts?: number;
}

// Common error names
type S3ErrorName = 
  | "NoSuchBucket"
  | "NoSuchKey" 
  | "BucketAlreadyExists"
  | "BucketNotEmpty"
  | "AccessDenied"
  | "InvalidBucketName"
  | "InvalidRequest"
  | "ServiceUnavailable"
  | "SlowDown"
  | "RequestTimeout";

Error Handling Examples:

import { 
  S3Client, 
  PutObjectCommand, 
  GetObjectCommand,
  S3ServiceException 
} from "@aws-sdk/client-s3";

const client = new S3Client({ region: "us-east-1" });

// Basic error handling
async function uploadWithErrorHandling(bucket: string, key: string, content: string) {
  try {
    const command = new PutObjectCommand({
      Bucket: bucket,
      Key: key,
      Body: content
    });
    
    const result = await client.send(command);
    console.log(`Upload successful: ${result.ETag}`);
    return result;
    
  } catch (error) {
    if (error instanceof S3ServiceException) {
      console.error(`S3 Error: ${error.name}`);
      console.error(`Status: ${error.$metadata.httpStatusCode}`);
      console.error(`Request ID: ${error.$metadata.requestId}`);
      
      // Handle specific error types
      switch (error.name) {
        case "NoSuchBucket":
          console.error("Bucket does not exist");
          break;
        case "AccessDenied":
          console.error("Insufficient permissions");
          break;
        case "InvalidBucketName":
          console.error("Bucket name is invalid");
          break;
        case "ServiceUnavailable":
          console.error("S3 service temporarily unavailable");
          break;
        default:
          console.error(`Unhandled S3 error: ${error.message}`);
      }
    } else {
      console.error("Non-S3 error:", error);
    }
    throw error;
  }
}

// Advanced error handling with retry logic
async function downloadWithRetry(
  bucket: string, 
  key: string, 
  maxRetries: number = 3
): Promise<string> {
  let lastError: Error;
  
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      const command = new GetObjectCommand({
        Bucket: bucket,
        Key: key
      });
      
      const response = await client.send(command);
      const content = await response.Body?.transformToString();
      
      if (!content) {
        throw new Error("Empty response body");
      }
      
      return content;
      
    } catch (error) {
      lastError = error as Error;
      
      if (error instanceof S3ServiceException) {
        // Don't retry certain errors
        const nonRetryableErrors = [
          "NoSuchBucket",
          "NoSuchKey", 
          "AccessDenied",
          "InvalidRequest"
        ];
        
        if (nonRetryableErrors.includes(error.name)) {
          console.error(`Non-retryable error: ${error.name}`);
          throw error;
        }
        
        // Retry server errors and throttling
        const retryableErrors = [
          "ServiceUnavailable",
          "SlowDown",
          "RequestTimeout"
        ];
        
        if (retryableErrors.includes(error.name) && attempt < maxRetries) {
          const delay = Math.min(1000 * Math.pow(2, attempt - 1), 10000);
          console.warn(`Attempt ${attempt} failed: ${error.name}. Retrying in ${delay}ms...`);
          await new Promise(resolve => setTimeout(resolve, delay));
          continue;
        }
      }
      
      if (attempt === maxRetries) {
        console.error(`All ${maxRetries} attempts failed. Last error:`, lastError.message);
        throw lastError;
      }
    }
  }
  
  throw lastError!;
}

// Error handling with custom error wrapper
class S3OperationError extends Error {
  constructor(
    message: string,
    public operation: string,
    public bucket: string,
    public key?: string,
    public originalError?: Error
  ) {
    super(message);
    this.name = "S3OperationError";
  }
}

async function safeS3Operation<T>(
  operation: string,
  bucket: string,
  key: string | undefined,
  fn: () => Promise<T>
): Promise<T> {
  try {
    return await fn();
  } catch (error) {
    if (error instanceof S3ServiceException) {
      const message = `${operation} failed: ${error.name} - ${error.message}`;
      throw new S3OperationError(message, operation, bucket, key, error);
    }
    throw error;
  }
}

// Usage with custom error wrapper
async function uploadSafely(bucket: string, key: string, content: string) {
  return safeS3Operation("upload", bucket, key, async () => {
    const command = new PutObjectCommand({
      Bucket: bucket,
      Key: key,
      Body: content
    });
    return await client.send(command);
  });
}

// Error handling with detailed logging
async function handleS3Error(error: unknown, context: string) {
  if (error instanceof S3ServiceException) {
    const errorDetails = {
      context,
      errorName: error.name,
      errorMessage: error.message,
      statusCode: error.$metadata.httpStatusCode,
      requestId: error.$metadata.requestId,
      retryable: error.$retryable?.throttling || false,
      timestamp: new Date().toISOString()
    };
    
    console.error("S3 Operation Failed:", JSON.stringify(errorDetails, null, 2));
    
    // Log to monitoring service (example)
    // await logToMonitoring(errorDetails);
    
    return errorDetails;
  } else {
    console.error(`Non-S3 error in ${context}:`, error);
    return { context, error: String(error), timestamp: new Date().toISOString() };
  }
}

// Example usage with comprehensive error handling
async function robustS3Upload(bucket: string, key: string, content: string) {
  try {
    return await uploadSafely(bucket, key, content);
  } catch (error) {
    await handleS3Error(error, `upload:${bucket}/${key}`);
    
    if (error instanceof S3OperationError && error.originalError instanceof S3ServiceException) {
      // Provide user-friendly error messages
      switch (error.originalError.name) {
        case "NoSuchBucket":
          throw new Error(`Bucket '${bucket}' does not exist. Please create it first.`);
        case "AccessDenied":
          throw new Error(`Access denied for bucket '${bucket}'. Check your permissions.`);
        case "InvalidBucketName":
          throw new Error(`Invalid bucket name '${bucket}'. Check naming requirements.`);
        default:
          throw new Error(`Upload failed: ${error.message}`);
      }
    }
    
    throw error;
  }
}