使用 AWS CLI 上传到 S3 时如何设置 Content-Type?

Posted

技术标签:

【中文标题】使用 AWS CLI 上传到 S3 时如何设置 Content-Type?【英文标题】:How do I set Content-Type when uploading to S3 with AWS CLI? 【发布时间】:2015-06-21 00:20:28 【问题描述】:

我正在尝试设置 S3 静态网站托管,但它似乎在我的任何没有在 AWS 控制台中设置 Content-Type 元数据字段的对象上返回 403。我不知道如何使用 AWS CLI 工具执行此操作。

使用--metadata 选项似乎有效:

$ 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"
    

但对象上的 Content-Type 字段在 AWS 控制台的“元数据”部分中不可见,当我尝试在浏览器中访问该文件时收到 403。

使用--content-type 选项也不起作用:

$ 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": 

虽然它似乎设置了某种特殊的 ContentType 属性,但 AWS 控制台中仍然没有 Content-Type 元数据字段,我也无法在浏览器中访问该文件。

我也尝试过类似的命令(aws s3 cpaws s3 sync),但没有成功。我已将存储桶策略设置为公开可读。

【问题讨论】:

【参考方案1】:

--content-type 的第二个示例是为对象设置内容类型的方法。显示的 JSON 响应将 HTTP 响应中的 Content-Type 标头映射到 ContentType 键,但它对应于对象的实际 Content-Type 标头。我确认使用--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": 

同样使用curl,我们可以看到设置了内容类型头:

$ 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

【讨论】:

如果我省略了--acl public-read 参数,这将不起作用。有没有办法让它在锁定对某个 IP 范围的访问的同时发挥作用,就像我在存储桶策略中所做的那样? 没关系,看来这个设置已经完全符合我的要求了:即使对象 ACL 设置为 public-read,存储桶策略仍然适用。【参考方案2】:

这不是 OP 想要的,但 Google 派了很多人到这里来。

如果您想设置已在 S3 上的对象的内容类型,而无需再次上传 --body,请参阅 How to change content type of Amazon S3 Objects

【讨论】:

【参考方案3】:

在 AWS 控制台中,即使下拉菜单中未列出内容类型,您也可以键入所需的内容类型。

【讨论】:

以上是关于使用 AWS CLI 上传到 S3 时如何设置 Content-Type?的主要内容,如果未能解决你的问题,请参考以下文章

aws s3 cli 如何确定要同步哪些文件?

Mac安装aws-cli全过程,通过命令行上传文件到aws s3协议服务器

上传文件到aws的s3存储的方法

AWS S3 CLI - 如何使用存储桶上设置的所有当前策略获取 JSON?

使用activestorage的直接上传上传到S3时如何指定前缀?

将对象上传到 S3 存储桶时如何触发 AWS Cloudformation 堆栈的更新?