Skip to content
Quest 02Beginner12 min

Upload Your First Pokédex Card

Time to store the first card: Treecko, #252, the Grass-type starter of Hoenn. One PutObject call uploads it — but a few extra fields decide how browsers, tools and caches treat it later.

What you'll learn

  • PutObject uploads a whole object (up to 5 GiB) and replaces anything already stored under that key.
  • Set ContentType on every upload, and use user metadata for small facts about the object.
  • S3 is strongly consistent: once a write succeeds, every read and listing sees it.

Section 01

Uploading with PutObject

PutObjectCommand takes the bucket, the key and a Body — a string, a Buffer, a Uint8Array or a stream. A single PUT can upload up to 5 GiB; above that (and usually above 100 MB) you use multipart upload, which is Quest 8.

If an object already exists under the key, the PUT replaces it. There's no “insert only” by default — Quest 6 shows how to ask for one.

Upload a cardJavaScript
import { PutObjectCommand } from "@aws-sdk/client-s3";

const card = { number: 252, name: "Treecko", types: ["grass"], region: "Hoenn" };

const { ETag } = await client.send(
  new PutObjectCommand({
    Bucket: "hoenn-pokedex-media",
    Key: "cards/0252-treecko.json",
    Body: JSON.stringify(card),
    ContentType: "application/json",
    Metadata: { generation: "3" },
  })
);

Section 02

Content type and metadata

S3 doesn't guess types from file names. Without ContentType the object is served as binary/octet-stream, so a browser downloads your card instead of displaying it and CloudFront can't compress it.

User metadata is a set of string key–value pairs sent as x-amz-meta-* headers. It comes back with every GET and HEAD, so tools can read the generation without downloading the card. Keep it small (2 KB in total), use lowercase keys, and remember you can't search by it — it's not an index.

FieldUse it for
ContentTypeHow clients should interpret the bytes
CacheControlHow long browsers and CDNs may cache it
MetadataSmall, string-only facts about the object
TaggingLabels for lifecycle rules, access control and cost reports (up to 10 per object)

Section 03

What comes back

A successful PUT returns an ETag, a fingerprint of the object. For a single-part upload without SSE-KMS it's the MD5 of the body; for multipart uploads it isn't, so treat it as an opaque version marker, not a checksum. Recent AWS SDKs also add a CRC32 checksum to uploads by default, and S3 verifies it.

New objects are encrypted at rest with SSE-S3 automatically (you'll see ServerSideEncryption: "AES256"). And since December 2020 S3 has been strongly consistent: after the PUT succeeds, any GET, HEAD or LIST sees the new object — no waiting, no stale reads.

Practice

Your turn

Upload Treecko's Pokédex card to cards/0252-treecko.json. Tell S3 it's JSON with ContentType, and tag it with user metadata generation: "3" so tools can read the generation without downloading the card.

Add ContentType: "application/json" and Metadata: { generation: "3" }.
Tab inserts two spaces. Press Escape, then Tab, to leave the editor. Control or Command plus Enter runs the code.
Simulated — no AWS calls

Check

Check your understanding

Quick Quiz · one question, as many tries as you need.

You upload cards/0252-treecko.json and immediately list cards/ from another Lambda function. What does the listing show?

Choose one answer.