[{"data":1,"prerenderedAt":2319},["ShallowReactive",2],{"post-\u002Fblog\u002Fpresigned-post-enforce-size-content-type":3},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"date":10,"author":11,"tags":12,"body":16,"_type":2313,"_id":2314,"_source":2315,"_file":2316,"_stem":2317,"_extension":2318},"\u002Fblog\u002Fpresigned-post-enforce-size-content-type","blog",false,"","Presigned POST: cap size and type before the upload starts","A presigned PUT signs a URL, not a byte count. A POST policy adds a size range and a content-type condition that S3 enforces while the body arrives.","2026-11-01","Clement Baranger",[13,14,15],"s3","security","uploads",{"type":17,"children":18,"toc":2304},"root",[19,27,34,89,95,123,143,231,240,292,329,335,340,621,639,656,673,699,741,751,784,790,800,1279,1306,1332,1555,1572,1717,1736,1744,1819,1836,1842,1862,1898,1910,1916,2064,2070,2293,2298],{"type":20,"tag":21,"props":22,"children":23},"element","p",{},[24],{"type":25,"value":26},"text","Every \"upload directly to S3\" feature starts the same way: the server hands the browser a presigned URL, the browser PUTs the file, the object appears. It ships in ten minutes, and quietly grants anyone holding that link the right to store four gigabytes of anything in your bucket. The fix is a different primitive: a presigned POST, where the permission is a document stating the size and type it will accept, signed before a single byte moves.",{"type":20,"tag":28,"props":29,"children":31},"h2",{"id":30},"the-short-version",[32],{"type":25,"value":33},"The short version",{"type":20,"tag":35,"props":36,"children":37},"ul",{},[38,44,57,71,84],{"type":20,"tag":39,"props":40,"children":41},"li",{},[42],{"type":25,"value":43},"A presigned URL signs one request — a host, a path, a verb. It never says how many bytes may follow.",{"type":20,"tag":39,"props":45,"children":46},{},[47,49,55],{"type":25,"value":48},"A presigned POST signs a ",{"type":20,"tag":50,"props":51,"children":52},"strong",{},[53],{"type":25,"value":54},"policy",{"type":25,"value":56},": a short JSON document listing conditions the upload must satisfy, such as a byte range and a content-type prefix.",{"type":20,"tag":39,"props":58,"children":59},{},[60,62,69],{"type":25,"value":61},"S3 checks the policy first, then counts the body as it arrives. An oversized file stops at ",{"type":20,"tag":63,"props":64,"children":66},"code",{"className":65},[],[67],{"type":25,"value":68},"400 EntityTooLarge",{"type":25,"value":70}," and nothing is stored.",{"type":20,"tag":39,"props":72,"children":73},{},[74,76,82],{"type":25,"value":75},"The limit lives in the signature, so it holds even if the browser is modified or replaced by ",{"type":20,"tag":63,"props":77,"children":79},{"className":78},[],[80],{"type":25,"value":81},"curl",{"type":25,"value":83},".",{"type":20,"tag":39,"props":85,"children":86},{},[87],{"type":25,"value":88},"The hours are in the audit, not the fix. The policy is ten lines; finding the stray objects that got past the old endpoint means listing the bucket and sorting by size.",{"type":20,"tag":28,"props":90,"children":92},{"id":91},"what-actually-happens",[93],{"type":25,"value":94},"What actually happens",{"type":20,"tag":21,"props":96,"children":97},{},[98,100,105,107,113,115,121],{"type":25,"value":99},"A presigned PUT is an HMAC over a canonical request: method, host, path, and the headers you chose to sign. ",{"type":20,"tag":50,"props":101,"children":102},{},[103],{"type":25,"value":104},"The body is not part of it.",{"type":25,"value":106}," The signature says \"PUT to this key is allowed until this time\", and the client decides what to send. You can sign ",{"type":20,"tag":63,"props":108,"children":110},{"className":109},[],[111],{"type":25,"value":112},"Content-Type",{"type":25,"value":114}," so a different type fails with ",{"type":20,"tag":63,"props":116,"children":118},{"className":117},[],[119],{"type":25,"value":120},"SignatureDoesNotMatch",{"type":25,"value":122},", which is a type check and not a size check — the length is still whatever the client announces.",{"type":20,"tag":21,"props":124,"children":125},{},[126,128,133,135,141],{"type":25,"value":127},"A presigned POST moves the constraints inside the signature. You write a policy document, base64-encode it, and HMAC-SHA256 the base64 with the signing key derived from your secret, the date, the region and ",{"type":20,"tag":63,"props":129,"children":131},{"className":130},[],[132],{"type":25,"value":13},{"type":25,"value":134},". That signature goes back to the client as a form field, with the encoded policy beside it. The browser then builds a ",{"type":20,"tag":63,"props":136,"children":138},{"className":137},[],[139],{"type":25,"value":140},"multipart\u002Fform-data",{"type":25,"value":142}," body: the auth fields, whatever metadata you allowed, and the file.",{"type":20,"tag":21,"props":144,"children":145},{},[146,148,154,156,162,164,170,172,178,180,186,188,193,195,201,202,208,209,215,216,222,223,229],{"type":25,"value":147},"The policy has two parts. ",{"type":20,"tag":63,"props":149,"children":151},{"className":150},[],[152],{"type":25,"value":153},"expiration",{"type":25,"value":155}," is an ISO8601 timestamp. ",{"type":20,"tag":63,"props":157,"children":159},{"className":158},[],[160],{"type":25,"value":161},"conditions",{"type":25,"value":163}," is an array where each entry is an exact match (",{"type":20,"tag":63,"props":165,"children":167},{"className":166},[],[168],{"type":25,"value":169},"{\"bucket\": \"uploads-prod\"}",{"type":25,"value":171},"), a prefix (",{"type":20,"tag":63,"props":173,"children":175},{"className":174},[],[176],{"type":25,"value":177},"[\"starts-with\", \"$key\", \"incoming\u002F\"]",{"type":25,"value":179},"), or the one numeric range the format supports: ",{"type":20,"tag":63,"props":181,"children":183},{"className":182},[],[184],{"type":25,"value":185},"[\"content-length-range\", 1, 10485760]",{"type":25,"value":187},", inclusive at both ends, in bytes. The array can also carry ",{"type":20,"tag":63,"props":189,"children":191},{"className":190},[],[192],{"type":25,"value":112},{"type":25,"value":194},", ",{"type":20,"tag":63,"props":196,"children":198},{"className":197},[],[199],{"type":25,"value":200},"Cache-Control",{"type":25,"value":194},{"type":20,"tag":63,"props":203,"children":205},{"className":204},[],[206],{"type":25,"value":207},"Content-Encoding",{"type":25,"value":194},{"type":20,"tag":63,"props":210,"children":212},{"className":211},[],[213],{"type":25,"value":214},"Expires",{"type":25,"value":194},{"type":20,"tag":63,"props":217,"children":219},{"className":218},[],[220],{"type":25,"value":221},"success_action_status",{"type":25,"value":194},{"type":20,"tag":63,"props":224,"children":226},{"className":225},[],[227],{"type":25,"value":228},"x-amz-meta-*",{"type":25,"value":230}," and the storage class.",{"type":20,"tag":21,"props":232,"children":233},{},[234],{"type":20,"tag":235,"props":236,"children":239},"img",{"alt":237,"src":238},"Flow of a presigned POST: the policy document is base64-encoded and HMAC-signed on your server, the browser posts the form fields with the file last, and S3 walks four checks — signature, declared fields, condition matches, then the byte count — before storing the object","\u002Fdiagrams\u002Fpresigned-post-enforce-size-content-type.svg",[],{"type":20,"tag":21,"props":241,"children":242},{},[243,245,251,253,259,261,266,268,274,276,282,284,290],{"type":25,"value":244},"One detail catches people who read the policy as plain string matching: in a ",{"type":20,"tag":63,"props":246,"children":248},{"className":247},[],[249],{"type":25,"value":250},"starts-with",{"type":25,"value":252}," condition on ",{"type":20,"tag":63,"props":254,"children":256},{"className":255},[],[257],{"type":25,"value":258},"$Content-Type",{"type":25,"value":260},", comma-separated values are treated as a list and ",{"type":20,"tag":50,"props":262,"children":263},{},[264],{"type":25,"value":265},"every",{"type":25,"value":267}," item has to pass. So ",{"type":20,"tag":63,"props":269,"children":271},{"className":270},[],[272],{"type":25,"value":273},"[\"starts-with\", \"$Content-Type\", \"image\u002F\"]",{"type":25,"value":275}," accepts ",{"type":20,"tag":63,"props":277,"children":279},{"className":278},[],[280],{"type":25,"value":281},"image\u002Fjpg,image\u002Fpng,image\u002Fgif",{"type":25,"value":283}," and rejects ",{"type":20,"tag":63,"props":285,"children":287},{"className":286},[],[288],{"type":25,"value":289},"image\u002Fjpg,text\u002Fplain",{"type":25,"value":291},". Other fields are compared as strings, commas included.",{"type":20,"tag":21,"props":293,"children":294},{},[295,297,303,305,311,313,319,321,327],{"type":25,"value":296},"The ",{"type":20,"tag":63,"props":298,"children":300},{"className":299},[],[301],{"type":25,"value":302},"key",{"type":25,"value":304}," field supports ",{"type":20,"tag":63,"props":306,"children":308},{"className":307},[],[309],{"type":25,"value":310},"${filename}",{"type":25,"value":312},", expanded from the client's filename before any condition is evaluated — which is why the condition tests the prefix ",{"type":20,"tag":63,"props":314,"children":316},{"className":315},[],[317],{"type":25,"value":318},"incoming\u002F",{"type":25,"value":320}," and not ",{"type":20,"tag":63,"props":322,"children":324},{"className":323},[],[325],{"type":25,"value":326},"incoming\u002F${filename}",{"type":25,"value":328},". AWS is explicit about that ordering.",{"type":20,"tag":28,"props":330,"children":332},{"id":331},"where-it-bites",[333],{"type":25,"value":334},"Where it bites",{"type":20,"tag":21,"props":336,"children":337},{},[338],{"type":25,"value":339},"Four checks run in a fixed order, each with its own error. The status codes overlap, so read the body.",{"type":20,"tag":341,"props":342,"children":343},"table",{},[344,368],{"type":20,"tag":345,"props":346,"children":347},"thead",{},[348],{"type":20,"tag":349,"props":350,"children":351},"tr",{},[352,358,363],{"type":20,"tag":353,"props":354,"children":355},"th",{},[356],{"type":25,"value":357},"Response",{"type":20,"tag":353,"props":359,"children":360},{},[361],{"type":25,"value":362},"Error code",{"type":20,"tag":353,"props":364,"children":365},{},[366],{"type":25,"value":367},"What it means",{"type":20,"tag":369,"props":370,"children":371},"tbody",{},[372,413,444,478,509,546,571,596],{"type":20,"tag":349,"props":373,"children":374},{},[375,385,394],{"type":20,"tag":376,"props":377,"children":378},"td",{},[379],{"type":20,"tag":63,"props":380,"children":382},{"className":381},[],[383],{"type":25,"value":384},"400",{"type":20,"tag":376,"props":386,"children":387},{},[388],{"type":20,"tag":63,"props":389,"children":391},{"className":390},[],[392],{"type":25,"value":393},"EntityTooLarge",{"type":20,"tag":376,"props":395,"children":396},{},[397,399,405,407],{"type":25,"value":398},"Over the maximum. The body carries ",{"type":20,"tag":63,"props":400,"children":402},{"className":401},[],[403],{"type":25,"value":404},"\u003CProposedSize>",{"type":25,"value":406}," and ",{"type":20,"tag":63,"props":408,"children":410},{"className":409},[],[411],{"type":25,"value":412},"\u003CMaxSizeAllowed>",{"type":20,"tag":349,"props":414,"children":415},{},[416,424,433],{"type":20,"tag":376,"props":417,"children":418},{},[419],{"type":20,"tag":63,"props":420,"children":422},{"className":421},[],[423],{"type":25,"value":384},{"type":20,"tag":376,"props":425,"children":426},{},[427],{"type":20,"tag":63,"props":428,"children":430},{"className":429},[],[431],{"type":25,"value":432},"EntityTooSmall",{"type":20,"tag":376,"props":434,"children":435},{},[436,438],{"type":25,"value":437},"Under the minimum. Carries ",{"type":20,"tag":63,"props":439,"children":441},{"className":440},[],[442],{"type":25,"value":443},"\u003CMinSizeAllowed>",{"type":20,"tag":349,"props":445,"children":446},{},[447,464,473],{"type":20,"tag":376,"props":448,"children":449},{},[450,456,458],{"type":20,"tag":63,"props":451,"children":453},{"className":452},[],[454],{"type":25,"value":455},"403",{"type":25,"value":457}," ",{"type":20,"tag":63,"props":459,"children":461},{"className":460},[],[462],{"type":25,"value":463},"AccessDenied",{"type":20,"tag":376,"props":465,"children":466},{},[467],{"type":20,"tag":63,"props":468,"children":470},{"className":469},[],[471],{"type":25,"value":472},"Invalid according to Policy: Policy Condition failed: [\"starts-with\", \"$Content-Type\", \"image\u002F\"]",{"type":20,"tag":376,"props":474,"children":475},{},[476],{"type":25,"value":477},"A condition did not match; the failing condition is quoted back",{"type":20,"tag":349,"props":479,"children":480},{},[481,495,504],{"type":20,"tag":376,"props":482,"children":483},{},[484,489,490],{"type":20,"tag":63,"props":485,"children":487},{"className":486},[],[488],{"type":25,"value":455},{"type":25,"value":457},{"type":20,"tag":63,"props":491,"children":493},{"className":492},[],[494],{"type":25,"value":463},{"type":20,"tag":376,"props":496,"children":497},{},[498],{"type":20,"tag":63,"props":499,"children":501},{"className":500},[],[502],{"type":25,"value":503},"Invalid according to Policy: Extra input fields: content-encoding",{"type":20,"tag":376,"props":505,"children":506},{},[507],{"type":25,"value":508},"The form sent a field the policy never declared",{"type":20,"tag":349,"props":510,"children":511},{},[512,526,535],{"type":20,"tag":376,"props":513,"children":514},{},[515,520,521],{"type":20,"tag":63,"props":516,"children":518},{"className":517},[],[519],{"type":25,"value":455},{"type":25,"value":457},{"type":20,"tag":63,"props":522,"children":524},{"className":523},[],[525],{"type":25,"value":463},{"type":20,"tag":376,"props":527,"children":528},{},[529],{"type":20,"tag":63,"props":530,"children":532},{"className":531},[],[533],{"type":25,"value":534},"Invalid according to Policy: Policy expired.",{"type":20,"tag":376,"props":536,"children":537},{},[538,539,544],{"type":25,"value":296},{"type":20,"tag":63,"props":540,"children":542},{"className":541},[],[543],{"type":25,"value":153},{"type":25,"value":545}," timestamp has passed",{"type":20,"tag":349,"props":547,"children":548},{},[549,557,566],{"type":20,"tag":376,"props":550,"children":551},{},[552],{"type":20,"tag":63,"props":553,"children":555},{"className":554},[],[556],{"type":25,"value":384},{"type":20,"tag":376,"props":558,"children":559},{},[560],{"type":20,"tag":63,"props":561,"children":563},{"className":562},[],[564],{"type":25,"value":565},"InvalidPolicyDocument",{"type":20,"tag":376,"props":567,"children":568},{},[569],{"type":25,"value":570},"\"The content of the form does not meet the conditions specified in the policy document\"",{"type":20,"tag":349,"props":572,"children":573},{},[574,582,591],{"type":20,"tag":376,"props":575,"children":576},{},[577],{"type":20,"tag":63,"props":578,"children":580},{"className":579},[],[581],{"type":25,"value":384},{"type":20,"tag":376,"props":583,"children":584},{},[585],{"type":20,"tag":63,"props":586,"children":588},{"className":587},[],[589],{"type":25,"value":590},"MaxPostPreDataLengthExceededError",{"type":20,"tag":376,"props":592,"children":593},{},[594],{"type":25,"value":595},"Everything before the file part exceeded 20 KB",{"type":20,"tag":349,"props":597,"children":598},{},[599,607,616],{"type":20,"tag":376,"props":600,"children":601},{},[602],{"type":20,"tag":63,"props":603,"children":605},{"className":604},[],[606],{"type":25,"value":384},{"type":20,"tag":376,"props":608,"children":609},{},[610],{"type":20,"tag":63,"props":611,"children":613},{"className":612},[],[614],{"type":25,"value":615},"IncorrectNumberOfFilesInPostRequest",{"type":20,"tag":376,"props":617,"children":618},{},[619],{"type":25,"value":620},"POST takes exactly one file per request",{"type":20,"tag":21,"props":622,"children":623},{},[624,629,631,637],{"type":20,"tag":50,"props":625,"children":626},{},[627],{"type":25,"value":628},"The limit is enforced while streaming.",{"type":25,"value":630}," S3 counts the file part as the body arrives, stops reading the moment the counter passes ",{"type":20,"tag":63,"props":632,"children":634},{"className":633},[],[635],{"type":25,"value":636},"max",{"type":25,"value":638},", and stores nothing partial — a documented property of the operation, not something to hope for.",{"type":20,"tag":21,"props":640,"children":641},{},[642,647,649,654],{"type":20,"tag":50,"props":643,"children":644},{},[645],{"type":25,"value":646},"The form has a size of its own.",{"type":25,"value":648}," Form data and boundaries, excluding the file contents, cannot exceed 20 KB. A normal policy is under 1 KB, so you only meet this by stuffing base64 thumbnails into ",{"type":20,"tag":63,"props":650,"children":652},{"className":651},[],[653],{"type":25,"value":228},{"type":25,"value":655},"; that metadata belongs in your database.",{"type":20,"tag":21,"props":657,"children":658},{},[659,664,666,671],{"type":20,"tag":50,"props":660,"children":661},{},[662],{"type":25,"value":663},"The file must be the last field.",{"type":25,"value":665}," AWS says it twice: \"make sure that the file field is the last field in the form\". Put ",{"type":20,"tag":63,"props":667,"children":669},{"className":668},[],[670],{"type":25,"value":302},{"type":25,"value":672}," after it and the key arrives missing.",{"type":20,"tag":21,"props":674,"children":675},{},[676,681,683,689,691,697],{"type":20,"tag":50,"props":677,"children":678},{},[679],{"type":25,"value":680},"No size cap on a PUT.",{"type":25,"value":682}," There is no ",{"type":20,"tag":63,"props":684,"children":686},{"className":685},[],[687],{"type":25,"value":688},"content-length-range",{"type":25,"value":690}," equivalent in a PUT signature; the nearest thing is signing a ",{"type":20,"tag":63,"props":692,"children":694},{"className":693},[],[695],{"type":25,"value":696},"Content-Length",{"type":25,"value":698}," header, which browsers do not let JavaScript set. That gap is what keeps the insecure pattern alive.",{"type":20,"tag":21,"props":700,"children":701},{},[702,707,709,715,717,723,725,731,733,739],{"type":20,"tag":50,"props":703,"children":704},{},[705],{"type":25,"value":706},"Provider deviation is real, and one is fatal.",{"type":25,"value":708}," Cloudflare R2 documents that ",{"type":20,"tag":63,"props":710,"children":712},{"className":711},[],[713],{"type":25,"value":714},"POST",{"type":25,"value":716}," — form uploads via HTML forms — \"is not currently supported\", and answers ",{"type":20,"tag":63,"props":718,"children":720},{"className":719},[],[721],{"type":25,"value":722},"501 Not Implemented",{"type":25,"value":724},", so the cap has to move to a Worker check or a HEAD-and-delete. MinIO implements it: its Java SDK ships a ",{"type":20,"tag":63,"props":726,"children":728},{"className":727},[],[729],{"type":25,"value":730},"PostPolicy",{"type":25,"value":732}," class with ",{"type":20,"tag":63,"props":734,"children":736},{"className":735},[],[737],{"type":25,"value":738},"addContentLengthRangeCondition()",{"type":25,"value":740},". Test the endpoint you actually run before promising a cap.",{"type":20,"tag":21,"props":742,"children":743},{},[744,749],{"type":20,"tag":50,"props":745,"children":746},{},[747],{"type":25,"value":748},"A delete is not a refund.",{"type":25,"value":750}," With versioning on, removing an oversized object leaves a noncurrent version, which stays billable.",{"type":20,"tag":21,"props":752,"children":753},{},[754,759,761,767,769,774,776,782],{"type":20,"tag":50,"props":755,"children":756},{},[757],{"type":25,"value":758},"The browser hides the reason.",{"type":25,"value":760}," When S3 stops reading a body the client is still writing, the socket drops mid-send and ",{"type":20,"tag":63,"props":762,"children":764},{"className":763},[],[765],{"type":25,"value":766},"fetch",{"type":25,"value":768}," often reports a network error instead of the ",{"type":20,"tag":63,"props":770,"children":772},{"className":771},[],[773],{"type":25,"value":384},{"type":25,"value":775},". Keep a ",{"type":20,"tag":63,"props":777,"children":779},{"className":778},[],[780],{"type":25,"value":781},"file.size",{"type":25,"value":783}," check so the common case produces a sentence a human can act on — and do not mistake it for a control: it is removable in one keystroke, and the policy is what remains.",{"type":20,"tag":28,"props":785,"children":787},{"id":786},"doing-it-right",[788],{"type":25,"value":789},"Doing it right",{"type":20,"tag":21,"props":791,"children":792},{},[793,798],{"type":20,"tag":50,"props":794,"children":795},{},[796],{"type":25,"value":797},"1. Write the policy with the four conditions that matter.",{"type":25,"value":799}," Bucket, key prefix, byte range, content type.",{"type":20,"tag":801,"props":802,"children":806},"pre",{"className":803,"code":804,"language":805,"meta":7,"style":7},"language-python shiki shiki-themes github-light-high-contrast github-dark-high-contrast","import boto3\n\ns3 = boto3.client(\"s3\", region_name=\"eu-west-3\")\nMAX_BYTES = 10 * 1024 * 1024          # 10 MiB\n\npost = s3.generate_presigned_post(\n    Bucket=\"uploads-prod\",\n    Key=\"incoming\u002F${filename}\",\n    Fields={\"Content-Type\": \"image\u002Fpng\"},\n    Conditions=[\n        {\"bucket\": \"uploads-prod\"},\n        [\"starts-with\", \"$key\", \"incoming\u002F\"],\n        [\"content-length-range\", 1, MAX_BYTES],\n        [\"starts-with\", \"$Content-Type\", \"image\u002F\"],\n        [\"success_action_status\", \"201\"],\n    ],\n    ExpiresIn=900,                     # 15 minutes\n)\n# post == {\"url\": \"https:\u002F\u002Fuploads-prod.s3.eu-west-3.amazonaws.com\u002F\", \"fields\": {...}}\n","python",[807],{"type":20,"tag":63,"props":808,"children":809},{"__ignoreMap":7},[810,828,838,887,931,939,957,980,1012,1050,1068,1094,1131,1165,1199,1225,1234,1262,1270],{"type":20,"tag":811,"props":812,"children":815},"span",{"class":813,"line":814},"line",1,[816,822],{"type":20,"tag":811,"props":817,"children":819},{"style":818},"--shiki-default:#A0111F;--shiki-dark:#FF9492",[820],{"type":25,"value":821},"import",{"type":20,"tag":811,"props":823,"children":825},{"style":824},"--shiki-default:#0E1116;--shiki-dark:#F0F3F6",[826],{"type":25,"value":827}," boto3\n",{"type":20,"tag":811,"props":829,"children":831},{"class":813,"line":830},2,[832],{"type":20,"tag":811,"props":833,"children":835},{"emptyLinePlaceholder":834},true,[836],{"type":25,"value":837},"\n",{"type":20,"tag":811,"props":839,"children":841},{"class":813,"line":840},3,[842,847,852,857,863,867,873,877,882],{"type":20,"tag":811,"props":843,"children":844},{"style":824},[845],{"type":25,"value":846},"s3 ",{"type":20,"tag":811,"props":848,"children":849},{"style":818},[850],{"type":25,"value":851},"=",{"type":20,"tag":811,"props":853,"children":854},{"style":824},[855],{"type":25,"value":856}," boto3.client(",{"type":20,"tag":811,"props":858,"children":860},{"style":859},"--shiki-default:#032563;--shiki-dark:#ADDCFF",[861],{"type":25,"value":862},"\"s3\"",{"type":20,"tag":811,"props":864,"children":865},{"style":824},[866],{"type":25,"value":194},{"type":20,"tag":811,"props":868,"children":870},{"style":869},"--shiki-default:#702C00;--shiki-dark:#FFB757",[871],{"type":25,"value":872},"region_name",{"type":20,"tag":811,"props":874,"children":875},{"style":818},[876],{"type":25,"value":851},{"type":20,"tag":811,"props":878,"children":879},{"style":859},[880],{"type":25,"value":881},"\"eu-west-3\"",{"type":20,"tag":811,"props":883,"children":884},{"style":824},[885],{"type":25,"value":886},")\n",{"type":20,"tag":811,"props":888,"children":890},{"class":813,"line":889},4,[891,897,902,907,912,917,921,925],{"type":20,"tag":811,"props":892,"children":894},{"style":893},"--shiki-default:#023B95;--shiki-dark:#91CBFF",[895],{"type":25,"value":896},"MAX_BYTES",{"type":20,"tag":811,"props":898,"children":899},{"style":818},[900],{"type":25,"value":901}," =",{"type":20,"tag":811,"props":903,"children":904},{"style":893},[905],{"type":25,"value":906}," 10",{"type":20,"tag":811,"props":908,"children":909},{"style":818},[910],{"type":25,"value":911}," *",{"type":20,"tag":811,"props":913,"children":914},{"style":893},[915],{"type":25,"value":916}," 1024",{"type":20,"tag":811,"props":918,"children":919},{"style":818},[920],{"type":25,"value":911},{"type":20,"tag":811,"props":922,"children":923},{"style":893},[924],{"type":25,"value":916},{"type":20,"tag":811,"props":926,"children":928},{"style":927},"--shiki-default:#66707B;--shiki-dark:#BDC4CC",[929],{"type":25,"value":930},"          # 10 MiB\n",{"type":20,"tag":811,"props":932,"children":934},{"class":813,"line":933},5,[935],{"type":20,"tag":811,"props":936,"children":937},{"emptyLinePlaceholder":834},[938],{"type":25,"value":837},{"type":20,"tag":811,"props":940,"children":942},{"class":813,"line":941},6,[943,948,952],{"type":20,"tag":811,"props":944,"children":945},{"style":824},[946],{"type":25,"value":947},"post ",{"type":20,"tag":811,"props":949,"children":950},{"style":818},[951],{"type":25,"value":851},{"type":20,"tag":811,"props":953,"children":954},{"style":824},[955],{"type":25,"value":956}," s3.generate_presigned_post(\n",{"type":20,"tag":811,"props":958,"children":960},{"class":813,"line":959},7,[961,966,970,975],{"type":20,"tag":811,"props":962,"children":963},{"style":869},[964],{"type":25,"value":965},"    Bucket",{"type":20,"tag":811,"props":967,"children":968},{"style":818},[969],{"type":25,"value":851},{"type":20,"tag":811,"props":971,"children":972},{"style":859},[973],{"type":25,"value":974},"\"uploads-prod\"",{"type":20,"tag":811,"props":976,"children":977},{"style":824},[978],{"type":25,"value":979},",\n",{"type":20,"tag":811,"props":981,"children":983},{"class":813,"line":982},8,[984,989,993,998,1003,1008],{"type":20,"tag":811,"props":985,"children":986},{"style":869},[987],{"type":25,"value":988},"    Key",{"type":20,"tag":811,"props":990,"children":991},{"style":818},[992],{"type":25,"value":851},{"type":20,"tag":811,"props":994,"children":995},{"style":859},[996],{"type":25,"value":997},"\"incoming\u002F$",{"type":20,"tag":811,"props":999,"children":1000},{"style":818},[1001],{"type":25,"value":1002},"{filename}",{"type":20,"tag":811,"props":1004,"children":1005},{"style":859},[1006],{"type":25,"value":1007},"\"",{"type":20,"tag":811,"props":1009,"children":1010},{"style":824},[1011],{"type":25,"value":979},{"type":20,"tag":811,"props":1013,"children":1015},{"class":813,"line":1014},9,[1016,1021,1025,1030,1035,1040,1045],{"type":20,"tag":811,"props":1017,"children":1018},{"style":869},[1019],{"type":25,"value":1020},"    Fields",{"type":20,"tag":811,"props":1022,"children":1023},{"style":818},[1024],{"type":25,"value":851},{"type":20,"tag":811,"props":1026,"children":1027},{"style":824},[1028],{"type":25,"value":1029},"{",{"type":20,"tag":811,"props":1031,"children":1032},{"style":859},[1033],{"type":25,"value":1034},"\"Content-Type\"",{"type":20,"tag":811,"props":1036,"children":1037},{"style":824},[1038],{"type":25,"value":1039},": ",{"type":20,"tag":811,"props":1041,"children":1042},{"style":859},[1043],{"type":25,"value":1044},"\"image\u002Fpng\"",{"type":20,"tag":811,"props":1046,"children":1047},{"style":824},[1048],{"type":25,"value":1049},"},\n",{"type":20,"tag":811,"props":1051,"children":1053},{"class":813,"line":1052},10,[1054,1059,1063],{"type":20,"tag":811,"props":1055,"children":1056},{"style":869},[1057],{"type":25,"value":1058},"    Conditions",{"type":20,"tag":811,"props":1060,"children":1061},{"style":818},[1062],{"type":25,"value":851},{"type":20,"tag":811,"props":1064,"children":1065},{"style":824},[1066],{"type":25,"value":1067},"[\n",{"type":20,"tag":811,"props":1069,"children":1071},{"class":813,"line":1070},11,[1072,1077,1082,1086,1090],{"type":20,"tag":811,"props":1073,"children":1074},{"style":824},[1075],{"type":25,"value":1076},"        {",{"type":20,"tag":811,"props":1078,"children":1079},{"style":859},[1080],{"type":25,"value":1081},"\"bucket\"",{"type":20,"tag":811,"props":1083,"children":1084},{"style":824},[1085],{"type":25,"value":1039},{"type":20,"tag":811,"props":1087,"children":1088},{"style":859},[1089],{"type":25,"value":974},{"type":20,"tag":811,"props":1091,"children":1092},{"style":824},[1093],{"type":25,"value":1049},{"type":20,"tag":811,"props":1095,"children":1097},{"class":813,"line":1096},12,[1098,1103,1108,1112,1117,1121,1126],{"type":20,"tag":811,"props":1099,"children":1100},{"style":824},[1101],{"type":25,"value":1102},"        [",{"type":20,"tag":811,"props":1104,"children":1105},{"style":859},[1106],{"type":25,"value":1107},"\"starts-with\"",{"type":20,"tag":811,"props":1109,"children":1110},{"style":824},[1111],{"type":25,"value":194},{"type":20,"tag":811,"props":1113,"children":1114},{"style":859},[1115],{"type":25,"value":1116},"\"$key\"",{"type":20,"tag":811,"props":1118,"children":1119},{"style":824},[1120],{"type":25,"value":194},{"type":20,"tag":811,"props":1122,"children":1123},{"style":859},[1124],{"type":25,"value":1125},"\"incoming\u002F\"",{"type":20,"tag":811,"props":1127,"children":1128},{"style":824},[1129],{"type":25,"value":1130},"],\n",{"type":20,"tag":811,"props":1132,"children":1134},{"class":813,"line":1133},13,[1135,1139,1144,1148,1153,1157,1161],{"type":20,"tag":811,"props":1136,"children":1137},{"style":824},[1138],{"type":25,"value":1102},{"type":20,"tag":811,"props":1140,"children":1141},{"style":859},[1142],{"type":25,"value":1143},"\"content-length-range\"",{"type":20,"tag":811,"props":1145,"children":1146},{"style":824},[1147],{"type":25,"value":194},{"type":20,"tag":811,"props":1149,"children":1150},{"style":893},[1151],{"type":25,"value":1152},"1",{"type":20,"tag":811,"props":1154,"children":1155},{"style":824},[1156],{"type":25,"value":194},{"type":20,"tag":811,"props":1158,"children":1159},{"style":893},[1160],{"type":25,"value":896},{"type":20,"tag":811,"props":1162,"children":1163},{"style":824},[1164],{"type":25,"value":1130},{"type":20,"tag":811,"props":1166,"children":1168},{"class":813,"line":1167},14,[1169,1173,1177,1181,1186,1190,1195],{"type":20,"tag":811,"props":1170,"children":1171},{"style":824},[1172],{"type":25,"value":1102},{"type":20,"tag":811,"props":1174,"children":1175},{"style":859},[1176],{"type":25,"value":1107},{"type":20,"tag":811,"props":1178,"children":1179},{"style":824},[1180],{"type":25,"value":194},{"type":20,"tag":811,"props":1182,"children":1183},{"style":859},[1184],{"type":25,"value":1185},"\"$Content-Type\"",{"type":20,"tag":811,"props":1187,"children":1188},{"style":824},[1189],{"type":25,"value":194},{"type":20,"tag":811,"props":1191,"children":1192},{"style":859},[1193],{"type":25,"value":1194},"\"image\u002F\"",{"type":20,"tag":811,"props":1196,"children":1197},{"style":824},[1198],{"type":25,"value":1130},{"type":20,"tag":811,"props":1200,"children":1202},{"class":813,"line":1201},15,[1203,1207,1212,1216,1221],{"type":20,"tag":811,"props":1204,"children":1205},{"style":824},[1206],{"type":25,"value":1102},{"type":20,"tag":811,"props":1208,"children":1209},{"style":859},[1210],{"type":25,"value":1211},"\"success_action_status\"",{"type":20,"tag":811,"props":1213,"children":1214},{"style":824},[1215],{"type":25,"value":194},{"type":20,"tag":811,"props":1217,"children":1218},{"style":859},[1219],{"type":25,"value":1220},"\"201\"",{"type":20,"tag":811,"props":1222,"children":1223},{"style":824},[1224],{"type":25,"value":1130},{"type":20,"tag":811,"props":1226,"children":1228},{"class":813,"line":1227},16,[1229],{"type":20,"tag":811,"props":1230,"children":1231},{"style":824},[1232],{"type":25,"value":1233},"    ],\n",{"type":20,"tag":811,"props":1235,"children":1237},{"class":813,"line":1236},17,[1238,1243,1247,1252,1257],{"type":20,"tag":811,"props":1239,"children":1240},{"style":869},[1241],{"type":25,"value":1242},"    ExpiresIn",{"type":20,"tag":811,"props":1244,"children":1245},{"style":818},[1246],{"type":25,"value":851},{"type":20,"tag":811,"props":1248,"children":1249},{"style":893},[1250],{"type":25,"value":1251},"900",{"type":20,"tag":811,"props":1253,"children":1254},{"style":824},[1255],{"type":25,"value":1256},",                     ",{"type":20,"tag":811,"props":1258,"children":1259},{"style":927},[1260],{"type":25,"value":1261},"# 15 minutes\n",{"type":20,"tag":811,"props":1263,"children":1265},{"class":813,"line":1264},18,[1266],{"type":20,"tag":811,"props":1267,"children":1268},{"style":824},[1269],{"type":25,"value":886},{"type":20,"tag":811,"props":1271,"children":1273},{"class":813,"line":1272},19,[1274],{"type":20,"tag":811,"props":1275,"children":1276},{"style":927},[1277],{"type":25,"value":1278},"# post == {\"url\": \"https:\u002F\u002Fuploads-prod.s3.eu-west-3.amazonaws.com\u002F\", \"fields\": {...}}\n",{"type":20,"tag":21,"props":1280,"children":1281},{},[1282,1288,1290,1296,1298,1304],{"type":20,"tag":63,"props":1283,"children":1285},{"className":1284},[],[1286],{"type":25,"value":1287},"success_action_status: 201",{"type":25,"value":1289}," makes S3 answer with an XML document containing the ",{"type":20,"tag":63,"props":1291,"children":1293},{"className":1292},[],[1294],{"type":25,"value":1295},"ETag",{"type":25,"value":1297},"; the default is ",{"type":20,"tag":63,"props":1299,"children":1301},{"className":1300},[],[1302],{"type":25,"value":1303},"204",{"type":25,"value":1305}," with an empty body, which leaves you nothing to confirm the upload with.",{"type":20,"tag":21,"props":1307,"children":1308},{},[1309,1314,1316,1322,1324,1330],{"type":20,"tag":50,"props":1310,"children":1311},{},[1312],{"type":25,"value":1313},"2. Post the fields first, the file last.",{"type":25,"value":1315}," Any client that appends ",{"type":20,"tag":63,"props":1317,"children":1319},{"className":1318},[],[1320],{"type":25,"value":1321},"files",{"type":25,"value":1323}," after ",{"type":20,"tag":63,"props":1325,"children":1327},{"className":1326},[],[1328],{"type":25,"value":1329},"data",{"type":25,"value":1331}," gets the ordering right by construction.",{"type":20,"tag":801,"props":1333,"children":1335},{"className":803,"code":1334,"language":805,"meta":7,"style":7},"import json, requests\n\npost = json.load(open(\"\u002Ftmp\u002Fpost.json\"))\nr = requests.post(\n    post[\"url\"],\n    data=post[\"fields\"],\n    files={\"file\": (\"huge.png\", open(\"\u002Ftmp\u002Ftoo-big.bin\", \"rb\"), \"image\u002Fpng\")},\n)\nprint(r.status_code, r.text[:300])\n",[1336],{"type":20,"tag":63,"props":1337,"children":1338},{"__ignoreMap":7},[1339,1351,1358,1394,1411,1428,1454,1525,1532],{"type":20,"tag":811,"props":1340,"children":1341},{"class":813,"line":814},[1342,1346],{"type":20,"tag":811,"props":1343,"children":1344},{"style":818},[1345],{"type":25,"value":821},{"type":20,"tag":811,"props":1347,"children":1348},{"style":824},[1349],{"type":25,"value":1350}," json, requests\n",{"type":20,"tag":811,"props":1352,"children":1353},{"class":813,"line":830},[1354],{"type":20,"tag":811,"props":1355,"children":1356},{"emptyLinePlaceholder":834},[1357],{"type":25,"value":837},{"type":20,"tag":811,"props":1359,"children":1360},{"class":813,"line":840},[1361,1365,1369,1374,1379,1384,1389],{"type":20,"tag":811,"props":1362,"children":1363},{"style":824},[1364],{"type":25,"value":947},{"type":20,"tag":811,"props":1366,"children":1367},{"style":818},[1368],{"type":25,"value":851},{"type":20,"tag":811,"props":1370,"children":1371},{"style":824},[1372],{"type":25,"value":1373}," json.load(",{"type":20,"tag":811,"props":1375,"children":1376},{"style":893},[1377],{"type":25,"value":1378},"open",{"type":20,"tag":811,"props":1380,"children":1381},{"style":824},[1382],{"type":25,"value":1383},"(",{"type":20,"tag":811,"props":1385,"children":1386},{"style":859},[1387],{"type":25,"value":1388},"\"\u002Ftmp\u002Fpost.json\"",{"type":20,"tag":811,"props":1390,"children":1391},{"style":824},[1392],{"type":25,"value":1393},"))\n",{"type":20,"tag":811,"props":1395,"children":1396},{"class":813,"line":889},[1397,1402,1406],{"type":20,"tag":811,"props":1398,"children":1399},{"style":824},[1400],{"type":25,"value":1401},"r ",{"type":20,"tag":811,"props":1403,"children":1404},{"style":818},[1405],{"type":25,"value":851},{"type":20,"tag":811,"props":1407,"children":1408},{"style":824},[1409],{"type":25,"value":1410}," requests.post(\n",{"type":20,"tag":811,"props":1412,"children":1413},{"class":813,"line":933},[1414,1419,1424],{"type":20,"tag":811,"props":1415,"children":1416},{"style":824},[1417],{"type":25,"value":1418},"    post[",{"type":20,"tag":811,"props":1420,"children":1421},{"style":859},[1422],{"type":25,"value":1423},"\"url\"",{"type":20,"tag":811,"props":1425,"children":1426},{"style":824},[1427],{"type":25,"value":1130},{"type":20,"tag":811,"props":1429,"children":1430},{"class":813,"line":941},[1431,1436,1440,1445,1450],{"type":20,"tag":811,"props":1432,"children":1433},{"style":869},[1434],{"type":25,"value":1435},"    data",{"type":20,"tag":811,"props":1437,"children":1438},{"style":818},[1439],{"type":25,"value":851},{"type":20,"tag":811,"props":1441,"children":1442},{"style":824},[1443],{"type":25,"value":1444},"post[",{"type":20,"tag":811,"props":1446,"children":1447},{"style":859},[1448],{"type":25,"value":1449},"\"fields\"",{"type":20,"tag":811,"props":1451,"children":1452},{"style":824},[1453],{"type":25,"value":1130},{"type":20,"tag":811,"props":1455,"children":1456},{"class":813,"line":959},[1457,1462,1466,1470,1475,1480,1485,1489,1493,1497,1502,1506,1511,1516,1520],{"type":20,"tag":811,"props":1458,"children":1459},{"style":869},[1460],{"type":25,"value":1461},"    files",{"type":20,"tag":811,"props":1463,"children":1464},{"style":818},[1465],{"type":25,"value":851},{"type":20,"tag":811,"props":1467,"children":1468},{"style":824},[1469],{"type":25,"value":1029},{"type":20,"tag":811,"props":1471,"children":1472},{"style":859},[1473],{"type":25,"value":1474},"\"file\"",{"type":20,"tag":811,"props":1476,"children":1477},{"style":824},[1478],{"type":25,"value":1479},": (",{"type":20,"tag":811,"props":1481,"children":1482},{"style":859},[1483],{"type":25,"value":1484},"\"huge.png\"",{"type":20,"tag":811,"props":1486,"children":1487},{"style":824},[1488],{"type":25,"value":194},{"type":20,"tag":811,"props":1490,"children":1491},{"style":893},[1492],{"type":25,"value":1378},{"type":20,"tag":811,"props":1494,"children":1495},{"style":824},[1496],{"type":25,"value":1383},{"type":20,"tag":811,"props":1498,"children":1499},{"style":859},[1500],{"type":25,"value":1501},"\"\u002Ftmp\u002Ftoo-big.bin\"",{"type":20,"tag":811,"props":1503,"children":1504},{"style":824},[1505],{"type":25,"value":194},{"type":20,"tag":811,"props":1507,"children":1508},{"style":859},[1509],{"type":25,"value":1510},"\"rb\"",{"type":20,"tag":811,"props":1512,"children":1513},{"style":824},[1514],{"type":25,"value":1515},"), ",{"type":20,"tag":811,"props":1517,"children":1518},{"style":859},[1519],{"type":25,"value":1044},{"type":20,"tag":811,"props":1521,"children":1522},{"style":824},[1523],{"type":25,"value":1524},")},\n",{"type":20,"tag":811,"props":1526,"children":1527},{"class":813,"line":982},[1528],{"type":20,"tag":811,"props":1529,"children":1530},{"style":824},[1531],{"type":25,"value":886},{"type":20,"tag":811,"props":1533,"children":1534},{"class":813,"line":1014},[1535,1540,1545,1550],{"type":20,"tag":811,"props":1536,"children":1537},{"style":893},[1538],{"type":25,"value":1539},"print",{"type":20,"tag":811,"props":1541,"children":1542},{"style":824},[1543],{"type":25,"value":1544},"(r.status_code, r.text[:",{"type":20,"tag":811,"props":1546,"children":1547},{"style":893},[1548],{"type":25,"value":1549},"300",{"type":20,"tag":811,"props":1551,"children":1552},{"style":824},[1553],{"type":25,"value":1554},"])\n",{"type":20,"tag":21,"props":1556,"children":1557},{},[1558,1563,1565,1570],{"type":20,"tag":50,"props":1559,"children":1560},{},[1561],{"type":25,"value":1562},"3. Replay the policy with a file that breaks it, before you ship it.",{"type":25,"value":1564}," Twelve megabytes against a ten-megabyte limit should return ",{"type":20,"tag":63,"props":1566,"children":1568},{"className":1567},[],[1569],{"type":25,"value":384},{"type":25,"value":1571}," with this body:",{"type":20,"tag":801,"props":1573,"children":1577},{"className":1574,"code":1575,"language":1576,"meta":7,"style":7},"language-xml shiki shiki-themes github-light-high-contrast github-dark-high-contrast","\u003CError>\n  \u003CCode>EntityTooLarge\u003C\u002FCode>\n  \u003CMessage>Your proposed upload exceeds the maximum allowed object size.\u003C\u002FMessage>\n  \u003CProposedSize>12582912\u003C\u002FProposedSize>\n  \u003CMaxSizeAllowed>10485760\u003C\u002FMaxSizeAllowed>\n\u003C\u002FError>\n","xml",[1578],{"type":20,"tag":63,"props":1579,"children":1580},{"__ignoreMap":7},[1581,1600,1626,1651,1676,1701],{"type":20,"tag":811,"props":1582,"children":1583},{"class":813,"line":814},[1584,1589,1595],{"type":20,"tag":811,"props":1585,"children":1586},{"style":824},[1587],{"type":25,"value":1588},"\u003C",{"type":20,"tag":811,"props":1590,"children":1592},{"style":1591},"--shiki-default:#024C1A;--shiki-dark:#72F088",[1593],{"type":25,"value":1594},"Error",{"type":20,"tag":811,"props":1596,"children":1597},{"style":824},[1598],{"type":25,"value":1599},">\n",{"type":20,"tag":811,"props":1601,"children":1602},{"class":813,"line":830},[1603,1608,1613,1618,1622],{"type":20,"tag":811,"props":1604,"children":1605},{"style":824},[1606],{"type":25,"value":1607},"  \u003C",{"type":20,"tag":811,"props":1609,"children":1610},{"style":1591},[1611],{"type":25,"value":1612},"Code",{"type":20,"tag":811,"props":1614,"children":1615},{"style":824},[1616],{"type":25,"value":1617},">EntityTooLarge\u003C\u002F",{"type":20,"tag":811,"props":1619,"children":1620},{"style":1591},[1621],{"type":25,"value":1612},{"type":20,"tag":811,"props":1623,"children":1624},{"style":824},[1625],{"type":25,"value":1599},{"type":20,"tag":811,"props":1627,"children":1628},{"class":813,"line":840},[1629,1633,1638,1643,1647],{"type":20,"tag":811,"props":1630,"children":1631},{"style":824},[1632],{"type":25,"value":1607},{"type":20,"tag":811,"props":1634,"children":1635},{"style":1591},[1636],{"type":25,"value":1637},"Message",{"type":20,"tag":811,"props":1639,"children":1640},{"style":824},[1641],{"type":25,"value":1642},">Your proposed upload exceeds the maximum allowed object size.\u003C\u002F",{"type":20,"tag":811,"props":1644,"children":1645},{"style":1591},[1646],{"type":25,"value":1637},{"type":20,"tag":811,"props":1648,"children":1649},{"style":824},[1650],{"type":25,"value":1599},{"type":20,"tag":811,"props":1652,"children":1653},{"class":813,"line":889},[1654,1658,1663,1668,1672],{"type":20,"tag":811,"props":1655,"children":1656},{"style":824},[1657],{"type":25,"value":1607},{"type":20,"tag":811,"props":1659,"children":1660},{"style":1591},[1661],{"type":25,"value":1662},"ProposedSize",{"type":20,"tag":811,"props":1664,"children":1665},{"style":824},[1666],{"type":25,"value":1667},">12582912\u003C\u002F",{"type":20,"tag":811,"props":1669,"children":1670},{"style":1591},[1671],{"type":25,"value":1662},{"type":20,"tag":811,"props":1673,"children":1674},{"style":824},[1675],{"type":25,"value":1599},{"type":20,"tag":811,"props":1677,"children":1678},{"class":813,"line":933},[1679,1683,1688,1693,1697],{"type":20,"tag":811,"props":1680,"children":1681},{"style":824},[1682],{"type":25,"value":1607},{"type":20,"tag":811,"props":1684,"children":1685},{"style":1591},[1686],{"type":25,"value":1687},"MaxSizeAllowed",{"type":20,"tag":811,"props":1689,"children":1690},{"style":824},[1691],{"type":25,"value":1692},">10485760\u003C\u002F",{"type":20,"tag":811,"props":1694,"children":1695},{"style":1591},[1696],{"type":25,"value":1687},{"type":20,"tag":811,"props":1698,"children":1699},{"style":824},[1700],{"type":25,"value":1599},{"type":20,"tag":811,"props":1702,"children":1703},{"class":813,"line":941},[1704,1709,1713],{"type":20,"tag":811,"props":1705,"children":1706},{"style":824},[1707],{"type":25,"value":1708},"\u003C\u002F",{"type":20,"tag":811,"props":1710,"children":1711},{"style":1591},[1712],{"type":25,"value":1594},{"type":20,"tag":811,"props":1714,"children":1715},{"style":824},[1716],{"type":25,"value":1599},{"type":20,"tag":21,"props":1718,"children":1719},{},[1720,1722,1727,1729,1734],{"type":25,"value":1721},"A ",{"type":20,"tag":63,"props":1723,"children":1725},{"className":1724},[],[1726],{"type":25,"value":455},{"type":25,"value":1728}," with \"Policy Condition failed\" instead means the form is not sending the field the condition demands — usually a missing ",{"type":20,"tag":63,"props":1730,"children":1732},{"className":1731},[],[1733],{"type":25,"value":112},{"type":25,"value":1735}," on the file part.",{"type":20,"tag":21,"props":1737,"children":1738},{},[1739],{"type":20,"tag":50,"props":1740,"children":1741},{},[1742],{"type":25,"value":1743},"4. Check what actually landed.",{"type":20,"tag":801,"props":1745,"children":1749},{"className":1746,"code":1747,"language":1748,"meta":7,"style":7},"language-bash shiki shiki-themes github-light-high-contrast github-dark-high-contrast","aws s3api head-object --bucket uploads-prod --key incoming\u002Flogo.png \\\n  --query '[ContentLength,ContentType]' --output text\n","bash",[1750],{"type":20,"tag":63,"props":1751,"children":1752},{"__ignoreMap":7},[1753,1796],{"type":20,"tag":811,"props":1754,"children":1755},{"class":813,"line":814},[1756,1761,1766,1771,1776,1781,1786,1791],{"type":20,"tag":811,"props":1757,"children":1758},{"style":869},[1759],{"type":25,"value":1760},"aws",{"type":20,"tag":811,"props":1762,"children":1763},{"style":859},[1764],{"type":25,"value":1765}," s3api",{"type":20,"tag":811,"props":1767,"children":1768},{"style":859},[1769],{"type":25,"value":1770}," head-object",{"type":20,"tag":811,"props":1772,"children":1773},{"style":893},[1774],{"type":25,"value":1775}," --bucket",{"type":20,"tag":811,"props":1777,"children":1778},{"style":859},[1779],{"type":25,"value":1780}," uploads-prod",{"type":20,"tag":811,"props":1782,"children":1783},{"style":893},[1784],{"type":25,"value":1785}," --key",{"type":20,"tag":811,"props":1787,"children":1788},{"style":859},[1789],{"type":25,"value":1790}," incoming\u002Flogo.png",{"type":20,"tag":811,"props":1792,"children":1793},{"style":818},[1794],{"type":25,"value":1795}," \\\n",{"type":20,"tag":811,"props":1797,"children":1798},{"class":813,"line":830},[1799,1804,1809,1814],{"type":20,"tag":811,"props":1800,"children":1801},{"style":893},[1802],{"type":25,"value":1803},"  --query",{"type":20,"tag":811,"props":1805,"children":1806},{"style":859},[1807],{"type":25,"value":1808}," '[ContentLength,ContentType]'",{"type":20,"tag":811,"props":1810,"children":1811},{"style":893},[1812],{"type":25,"value":1813}," --output",{"type":20,"tag":811,"props":1815,"children":1816},{"style":859},[1817],{"type":25,"value":1818}," text\n",{"type":20,"tag":21,"props":1820,"children":1821},{},[1822,1827,1829,1834],{"type":20,"tag":50,"props":1823,"children":1824},{},[1825],{"type":25,"value":1826},"5. Where POST is unavailable, enforce outside the signature.",{"type":25,"value":1828}," A Worker, a reverse proxy or a gateway can read ",{"type":20,"tag":63,"props":1830,"children":1832},{"className":1831},[],[1833],{"type":25,"value":696},{"type":25,"value":1835}," before accepting the body; HEAD-then-delete is the fallback and is not atomic. Name the one you rely on in the runbook.",{"type":20,"tag":28,"props":1837,"children":1839},{"id":1838},"how-s3-explorer-fits",[1840],{"type":25,"value":1841},"How S3 Explorer fits",{"type":20,"tag":21,"props":1843,"children":1844},{},[1845,1847,1852,1854,1860],{"type":25,"value":1846},"A policy states what a client may send; the object records what it sent, and the two disagree more often than expected — a ",{"type":20,"tag":63,"props":1848,"children":1850},{"className":1849},[],[1851],{"type":25,"value":112},{"type":25,"value":1853}," that is quietly ",{"type":20,"tag":63,"props":1855,"children":1857},{"className":1856},[],[1858],{"type":25,"value":1859},"application\u002Foctet-stream",{"type":25,"value":1861}," because the browser omitted it.",{"type":20,"tag":21,"props":1863,"children":1864},{},[1865,1867,1872,1873,1878,1880,1885,1887,1896],{"type":25,"value":1866},"S3 Explorer shows both sides. Bucket and folder browsing reaches the uploaded key, the ",{"type":20,"tag":50,"props":1868,"children":1869},{},[1870],{"type":25,"value":1871},"Content",{"type":25,"value":406},{"type":20,"tag":50,"props":1874,"children":1875},{},[1876],{"type":25,"value":1877},"Metadata",{"type":25,"value":1879}," tabs show the stored content type, size and user metadata exactly as S3 holds them, and the image preview shows whether that stored type is the one a browser will render. ",{"type":20,"tag":50,"props":1881,"children":1882},{},[1883],{"type":25,"value":1884},"Multiple connection profiles",{"type":25,"value":1886}," let you post the same form to AWS and to a compatible endpoint, and compare the results. ",{"type":20,"tag":1888,"props":1889,"children":1893},"a",{"href":1890,"rel":1891},"https:\u002F\u002Fs3explorer.accessdevops.com",[1892],"nofollow",[1894],{"type":25,"value":1895},"S3 Explorer",{"type":25,"value":1897}," runs on Windows, macOS and Linux.",{"type":20,"tag":21,"props":1899,"children":1900},{},[1901,1903,1909],{"type":25,"value":1902},"The other half of the same problem — how long the permission lasts — is covered in ",{"type":20,"tag":1888,"props":1904,"children":1906},{"href":1905},"\u002Fblog\u002Fpresigned-url-seven-day-ceiling",[1907],{"type":25,"value":1908},"presigned URLs expire at seven days",{"type":25,"value":83},{"type":20,"tag":28,"props":1911,"children":1913},{"id":1912},"checklist",[1914],{"type":25,"value":1915},"Checklist",{"type":20,"tag":35,"props":1917,"children":1920},{"className":1918},[1919],"contains-task-list",[1921,1939,1948,1970,1992,2001,2018,2034],{"type":20,"tag":39,"props":1922,"children":1925},{"className":1923},[1924],"task-list-item",[1926,1931,1933,1938],{"type":20,"tag":1927,"props":1928,"children":1930},"input",{"disabled":834,"type":1929},"checkbox",[],{"type":25,"value":1932}," No upload path issues a presigned PUT to an untrusted client; each uses a POST policy with ",{"type":20,"tag":63,"props":1934,"children":1936},{"className":1935},[],[1937],{"type":25,"value":688},{"type":25,"value":83},{"type":20,"tag":39,"props":1940,"children":1942},{"className":1941},[1924],[1943,1946],{"type":20,"tag":1927,"props":1944,"children":1945},{"disabled":834,"type":1929},[],{"type":25,"value":1947}," The policy pins the bucket and a key prefix, so a client cannot write outside its own folder.",{"type":20,"tag":39,"props":1949,"children":1951},{"className":1950},[1924],[1952,1955,1956,1961,1963,1968],{"type":20,"tag":1927,"props":1953,"children":1954},{"disabled":834,"type":1929},[],{"type":25,"value":457},{"type":20,"tag":63,"props":1957,"children":1959},{"className":1958},[],[1960],{"type":25,"value":112},{"type":25,"value":1962}," has a ",{"type":20,"tag":63,"props":1964,"children":1966},{"className":1965},[],[1967],{"type":25,"value":250},{"type":25,"value":1969}," condition and the form sends the field, rather than letting the browser guess.",{"type":20,"tag":39,"props":1971,"children":1973},{"className":1972},[1924],[1974,1977,1979,1984,1986,1991],{"type":20,"tag":1927,"props":1975,"children":1976},{"disabled":834,"type":1929},[],{"type":25,"value":1978}," A 12 MB file has been posted against a 10 MB policy and returned ",{"type":20,"tag":63,"props":1980,"children":1982},{"className":1981},[],[1983],{"type":25,"value":68},{"type":25,"value":1985}," with ",{"type":20,"tag":63,"props":1987,"children":1989},{"className":1988},[],[1990],{"type":25,"value":1662},{"type":25,"value":83},{"type":20,"tag":39,"props":1993,"children":1995},{"className":1994},[1924],[1996,1999],{"type":20,"tag":1927,"props":1997,"children":1998},{"disabled":834,"type":1929},[],{"type":25,"value":2000}," The multipart body was read directly: no field the policy does not declare, and the file is last.",{"type":20,"tag":39,"props":2002,"children":2004},{"className":2003},[1924],[2005,2008,2010,2016],{"type":20,"tag":1927,"props":2006,"children":2007},{"disabled":834,"type":1929},[],{"type":25,"value":2009}," Every provider in the deployment is tested for POST Object support; the R2-style ",{"type":20,"tag":63,"props":2011,"children":2013},{"className":2012},[],[2014],{"type":25,"value":2015},"501",{"type":25,"value":2017}," has a named fallback.",{"type":20,"tag":39,"props":2019,"children":2021},{"className":2020},[1924],[2022,2025,2027,2032],{"type":20,"tag":1927,"props":2023,"children":2024},{"disabled":834,"type":1929},[],{"type":25,"value":2026}," The client still checks ",{"type":20,"tag":63,"props":2028,"children":2030},{"className":2029},[],[2031],{"type":25,"value":781},{"type":25,"value":2033}," for the user's benefit, and the code says it is not a security control.",{"type":20,"tag":39,"props":2035,"children":2037},{"className":2036},[1924],[2038,2041,2042,2047,2049,2055,2057,2062],{"type":20,"tag":1927,"props":2039,"children":2040},{"disabled":834,"type":1929},[],{"type":25,"value":457},{"type":20,"tag":63,"props":2043,"children":2045},{"className":2044},[],[2046],{"type":25,"value":221},{"type":25,"value":2048}," is ",{"type":20,"tag":63,"props":2050,"children":2052},{"className":2051},[],[2053],{"type":25,"value":2054},"201",{"type":25,"value":2056}," and the returned ",{"type":20,"tag":63,"props":2058,"children":2060},{"className":2059},[],[2061],{"type":25,"value":1295},{"type":25,"value":2063}," is stored against the object key.",{"type":20,"tag":28,"props":2065,"children":2067},{"id":2066},"sources",[2068],{"type":25,"value":2069},"Sources",{"type":20,"tag":35,"props":2071,"children":2072},{},[2073,2119,2158,2170,2211,2223,2257],{"type":20,"tag":39,"props":2074,"children":2075},{},[2076,2083,2085,2090,2091,2097,2099,2104,2105,2110,2112,2117],{"type":20,"tag":1888,"props":2077,"children":2080},{"href":2078,"rel":2079},"https:\u002F\u002Fdocs.aws.amazon.com\u002FAmazonS3\u002Flatest\u002Fuserguide\u002FRESTObjectPOST.html",[1892],[2081],{"type":25,"value":2082},"Amazon S3 — POST Object",{"type":25,"value":2084},": form fields, ",{"type":20,"tag":63,"props":2086,"children":2088},{"className":2087},[],[2089],{"type":25,"value":221},{"type":25,"value":457},{"type":20,"tag":63,"props":2092,"children":2094},{"className":2093},[],[2095],{"type":25,"value":2096},"200",{"type":25,"value":2098},"\u002F",{"type":20,"tag":63,"props":2100,"children":2102},{"className":2101},[],[2103],{"type":25,"value":2054},{"type":25,"value":2098},{"type":20,"tag":63,"props":2106,"children":2108},{"className":2107},[],[2109],{"type":25,"value":1303},{"type":25,"value":2111}," (default ",{"type":20,"tag":63,"props":2113,"children":2115},{"className":2114},[],[2116],{"type":25,"value":1303},{"type":25,"value":2118},"), \"the file field is the last field in the form\", one file per request, no partial objects.",{"type":20,"tag":39,"props":2120,"children":2121},{},[2122,2129,2131,2136,2137,2142,2144,2149,2151,2156],{"type":20,"tag":1888,"props":2123,"children":2126},{"href":2124,"rel":2125},"https:\u002F\u002Fdocs.aws.amazon.com\u002FAmazonS3\u002Flatest\u002Fuserguide\u002Fsigv4-HTTPPOSTConstructPolicy.html",[1892],[2127],{"type":25,"value":2128},"Amazon S3 — POST policy",{"type":25,"value":2130},": exact, ",{"type":20,"tag":63,"props":2132,"children":2134},{"className":2133},[],[2135],{"type":25,"value":250},{"type":25,"value":406},{"type":20,"tag":63,"props":2138,"children":2140},{"className":2139},[],[2141],{"type":25,"value":688},{"type":25,"value":2143}," conditions, the comma-separated ",{"type":20,"tag":63,"props":2145,"children":2147},{"className":2146},[],[2148],{"type":25,"value":112},{"type":25,"value":2150}," rule, ",{"type":20,"tag":63,"props":2152,"children":2154},{"className":2153},[],[2155],{"type":25,"value":310},{"type":25,"value":2157}," expansion before matching.",{"type":20,"tag":39,"props":2159,"children":2160},{},[2161,2168],{"type":20,"tag":1888,"props":2162,"children":2165},{"href":2163,"rel":2164},"https:\u002F\u002Fdocs.aws.amazon.com\u002FAmazonS3\u002Flatest\u002Fuserguide\u002FHTTPPOSTForms.html",[1892],[2166],{"type":25,"value":2167},"Amazon S3 — HTML forms",{"type":25,"value":2169},": \"form data and boundaries (excluding the contents of the file) cannot exceed 20 KB\".",{"type":20,"tag":39,"props":2171,"children":2172},{},[2173,2180,2181,2186,2187,2192,2193,2198,2199,2204,2205,2210],{"type":20,"tag":1888,"props":2174,"children":2177},{"href":2175,"rel":2176},"https:\u002F\u002Fdocs.aws.amazon.com\u002FAmazonS3\u002Flatest\u002FAPI\u002FAPI_Error.html",[1892],[2178],{"type":25,"value":2179},"Amazon S3 — Error responses",{"type":25,"value":1039},{"type":20,"tag":63,"props":2182,"children":2184},{"className":2183},[],[2185],{"type":25,"value":393},{"type":25,"value":194},{"type":20,"tag":63,"props":2188,"children":2190},{"className":2189},[],[2191],{"type":25,"value":432},{"type":25,"value":194},{"type":20,"tag":63,"props":2194,"children":2196},{"className":2195},[],[2197],{"type":25,"value":565},{"type":25,"value":194},{"type":20,"tag":63,"props":2200,"children":2202},{"className":2201},[],[2203],{"type":25,"value":590},{"type":25,"value":194},{"type":20,"tag":63,"props":2206,"children":2208},{"className":2207},[],[2209],{"type":25,"value":615},{"type":25,"value":83},{"type":20,"tag":39,"props":2212,"children":2213},{},[2214,2221],{"type":20,"tag":1888,"props":2215,"children":2218},{"href":2216,"rel":2217},"https:\u002F\u002Fdocs.aws.amazon.com\u002FAmazonS3\u002Flatest\u002Fuserguide\u002Fupload-objects.html",[1892],[2219],{"type":25,"value":2220},"Amazon S3 — Uploading objects",{"type":25,"value":2222},": a single PUT operation is limited to 5 GB, also the ceiling for a single POST.",{"type":20,"tag":39,"props":2224,"children":2225},{},[2226,2233,2235,2240,2242,2247,2249,2255],{"type":20,"tag":1888,"props":2227,"children":2230},{"href":2228,"rel":2229},"https:\u002F\u002Fdevelopers.cloudflare.com\u002Fr2\u002Fapi\u002Fs3\u002Fpresigned-urls\u002F",[1892],[2231],{"type":25,"value":2232},"Cloudflare R2 — Presigned URLs",{"type":25,"value":2234},": \"",{"type":20,"tag":63,"props":2236,"children":2238},{"className":2237},[],[2239],{"type":25,"value":714},{"type":25,"value":2241}," … is not currently supported\"; signing ",{"type":20,"tag":63,"props":2243,"children":2245},{"className":2244},[],[2246],{"type":25,"value":112},{"type":25,"value":2248}," on a PUT yields ",{"type":20,"tag":63,"props":2250,"children":2252},{"className":2251},[],[2253],{"type":25,"value":2254},"403 SignatureDoesNotMatch",{"type":25,"value":2256}," when it changes.",{"type":20,"tag":39,"props":2258,"children":2259},{},[2260,2272,2273,2284,2285,2291],{"type":20,"tag":1888,"props":2261,"children":2264},{"href":2262,"rel":2263},"https:\u002F\u002Fminio-java.min.io\u002Fio\u002Fminio\u002FPostPolicy.html",[1892],[2265,2267],{"type":25,"value":2266},"MinIO Java SDK — ",{"type":20,"tag":63,"props":2268,"children":2270},{"className":2269},[],[2271],{"type":25,"value":730},{"type":25,"value":194},{"type":20,"tag":1888,"props":2274,"children":2277},{"href":2275,"rel":2276},"https:\u002F\u002Fminio-java.min.io\u002Fio\u002Fminio\u002FMinioClient.html",[1892],[2278],{"type":20,"tag":63,"props":2279,"children":2281},{"className":2280},[],[2282],{"type":25,"value":2283},"getPresignedPostFormData",{"type":25,"value":1039},{"type":20,"tag":63,"props":2286,"children":2288},{"className":2287},[],[2289],{"type":25,"value":2290},"addContentLengthRangeCondition",{"type":25,"value":2292},", \"file must be added at last\".",{"type":20,"tag":21,"props":2294,"children":2295},{},[2296],{"type":25,"value":2297},"Error strings and limits read from vendor documentation on 1 November 2026, quoted rather than paraphrased.",{"type":20,"tag":2299,"props":2300,"children":2301},"style",{},[2302],{"type":25,"value":2303},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":7,"searchDepth":830,"depth":830,"links":2305},[2306,2307,2308,2309,2310,2311,2312],{"id":30,"depth":830,"text":33},{"id":91,"depth":830,"text":94},{"id":331,"depth":830,"text":334},{"id":786,"depth":830,"text":789},{"id":1838,"depth":830,"text":1841},{"id":1912,"depth":830,"text":1915},{"id":2066,"depth":830,"text":2069},"markdown","content:blog:presigned-post-enforce-size-content-type.md","content","blog\u002Fpresigned-post-enforce-size-content-type.md","blog\u002Fpresigned-post-enforce-size-content-type","md",1793533052980]