Alek Storm
Alek Storm

Reputation: 777

How do I set Content-Type when uploading to S3 with AWS CLI?

I'm trying to set up S3 static website hosting, but it appears to return 403 on any of my objects that don't have the Content-Type metadata field set in the AWS console. I cannot figure out how to do this with the AWS CLI tool.

Using the --metadata option appears to work:

$ aws s3api put-object --bucket <bucket> --key foo.html --body foo.html --metadata Content-Type=text/html
{
    "ETag": "\"fd5ff7743e5ed1e1c304eb1c34e8e39f\""
}
$ aws s3api head-object --bucket <bucket> --key foo.html
{
    "AcceptRanges": "bytes",
    "ContentType": "binary/octet-stream",
    "LastModified": "Wed, 15 Apr 2015 06:39:48 GMT",
    "ContentLength": 189,
    "ETag": "\"fd5ff7743e5ed1e1c304eb1c34e8e39f\"",
    "Metadata": {
        "content-type": "text/html"
    }
}

But the Content-Type field on the object isn't visible in the "Metadata" section of the AWS console, and I get a 403 when trying to access the file in a browser.

Using the --content-type option also doesn't work:

$ aws s3api put-object --bucket <bucket> --key foo.html --body foo.html --content-type text/html
{
    "ETag": "\"fd5ff7743e5ed1e1c304eb1c34e8e39f\""
}
$ aws s3api head-object --bucket <bucket> --key foo.html
{
    "AcceptRanges": "bytes",
    "ContentType": "text/html",
    "LastModified": "Wed, 15 Apr 2015 06:46:49 GMT",
    "ContentLength": 189,
    "ETag": "\"fd5ff7743e5ed1e1c304eb1c34e8e39f\"",
    "Metadata": {}
}

While it appears to set some sort of special ContentType property, there still isn't a Content-Type metadata field in the AWS console, nor can I access the file in a browser.

I've also tried similar commands (aws s3 cp, aws s3 sync), with no luck. I have the bucket policy set to publicly-readable.

Upvotes: 40

Views: 136148

Answers (4)

wz2b
wz2b

Reputation: 1025

This problem is old, but it's still really vexing. I tried creating a lambda to look at the content type and fix it up and it caused some kind of recursion. I can't believe Amazon hasn't provided a way to fix this, at least the way Apache and others do it by letting you specify your own file extension to mime type mapping. Or, even better, just do the right thing. If I upload a file that's named xyzzy.js then it should be pretty obvious that it's mime type should not be "text/plain." The fact that this screws up S3 backed CloudFront makes it even more boggling to me that it hasn't been mitigated.

Upvotes: -1

Bruno Bronosky
Bruno Bronosky

Reputation: 70519

This is not what the OP was looking for, but Google sends a lot of people here.

If you are wanting to set the content type of an object that is already on S3 without having to upload the --body again, see How to change content type of Amazon S3 Objects

Upvotes: 12

chris
chris

Reputation: 51

In the AWS console, you can key in the content-type that you want even if the content-type is not listed in the drop-down.

Upvotes: 5

jamesls
jamesls

Reputation: 5618

Your second example with --content-type is the way to set content type for an object. The JSON response displayed is mapping the Content-Type header in the HTTP response to the ContentType key, but it corresponds to the actual Content-Type header of the object. I confirmed that the content type value does show up in the metadata section in the console when using --content-type.

$ aws s3api put-object --bucket bucket --key foo.json --body foo.json --content-type application/json --acl public-read

$ aws s3api head-object --bucket jamesls-test-sync --key foo.json
{
    "AcceptRanges": "bytes",
    "ContentType": "application/json",
    "LastModified": "Wed, 15 Apr 2015 17:18:58 GMT",
    "ContentLength": 0,
    "ETag": "\"d41d8cd98f00b204e9800998ecf8427e\"",
    "Metadata": {}
}

Also using curl, we can see the content type header is set:

$ curl -I https://bucket.s3.amazonaws.com/foo.json
HTTP/1.1 200 OK
x-amz-id-2: ZlSg1aDUBu7z+9gWUg24uRn2TioI0hk2AGBBZ1iVbpUkv8RTrHWovzbHxL/y21Qe
x-amz-request-id: 8568C73EB95EE5A6
Date: Wed, 15 Apr 2015 17:20:42 GMT
Last-Modified: Wed, 15 Apr 2015 17:18:58 GMT
ETag: "d41d8cd98f00b204e9800998ecf8427e"
Accept-Ranges: bytes
Content-Type: application/json
Content-Length: 0
Server: AmazonS3

Upvotes: 47

Related Questions