Amazon S3下载 index.html 而不是服务

我已经设置了 AmazonS3来服务我的静态站点 speakeasylinguistics.com。所有的 DNS 的东西似乎工作正常,因为 dig +recurse +trace www.speakeasylinguistics.com输出正确的 DNS 信息。

但是,当您使用 用浏览器访问网站端点,index.html页面下载,而不是被服务。我如何解决这个问题?

我试过 Chrome,Safari,FF。所有人都会这样。我使用 亚马逊的演练托管一个自定义域到一个 T。

37080 次浏览

运行 curl-I 对照你发布的 url 会得到以下结果:

curl -I http://speakeasylinguistics.com.s3-website-us-east-1.amazonaws.com/
HTTP/1.1 200 OK
x-amz-id-2: DmfUpbglWQ/evhF3pTiXYf6c+gIE8j0F6mw7VmATOpfc29V5tb5YTeojC68jE7Rd
x-amz-request-id: E233603809AF9956
Date: Sun, 18 Aug 2013 07:58:55 GMT
Content-Disposition: attachment
Last-Modified: Sun, 18 Aug 2013 07:05:20 GMT
ETag: "eacded76ceb4831aaeae2805c892fa1c"
Content-Type: text/html
Content-Length: 2585
Server: AmazonS3

这句话就是罪魁祸首:

Content-Disposition: attachment

如果您正在使用 AWS 控制台,我相信可以通过选择 S3中的文件并通过删除此属性来修改其元数据来更改这个属性。

如果你正在这样做的程序,你可以设置 ContentType和/或 ContentDisposition参数在您的上传。

[ PHP 示例]

      $output = $s3->putObject(array(
'Bucket' => $bucket,
'Key' => md5($share). '.html',
'ContentType' => 'text/html',
'Body' => $share,
));

PutObject 文档

如果您使用的是 Hashicorp Terraform,您可以在 Aws _ s3 _ bucket _ object上指定 content-type,如下所示

resource "aws_s3_bucket_object" "index" {
bucket = "yourbucketnamehere"
key = "index.html"
content = "<h1>Hello, world</h1>"


content_type = "text/html"
}

这将在浏览器中适当地提供内容。

编辑24/05/22: 正如在这个答案的评论中提到的,Terraform 现在有了一个模块帮助上传文件并正确设置它们的 content-type属性

如果您使用的是 AWS S3 Bitbucket 管道 Python,那么添加参数 < em > content _ type 如下:

S3 _ upload.py

def upload_to_s3(bucket, artefact, bucket_key, content_type):
...


def main():
...
parser.add_argument("content_type", help="Content Type File")
...


if not upload_to_s3(args.bucket, args.artefact, args.bucket_key, args.content_type):

修改 管道如下:

...
- python s3_upload.py bucket_name file key content_type
...

其中 Content _ type参数可以是以下内容之一: MIME 类型(IANA 媒体类型)

如果你们想用 Boto3和 python 3.7或更高版本上传,请尝试使用

s3 = boto3.client('s3')
S3.upload_file(local_file,bucket,S3_file,ExtraArgs={'ContentType':'text/html'})

更新内容类型

我最近也遇到了同样的问题,问题是 CloudFront & S3 Origin 的行为发生了变化, 如果你的 S3Bucket 配置为静态网站,你需要改变你的原点为 HTTPS://端点,而不是从下拉菜单中选择 S3原点,如果你使用 terraform,你的原点应该是 aws _ S3 _ bucket。使用 var.网站 _ 端点代替 aws _ s3 _ bucket。Var.< strong > bucket _ domain _ name

请参阅 AWS 文档在这里

对于其他面临这个问题的人来说,在 Properties > Static website hosting下面的 URL 中有一个输入错误。例如,提供的 URL 是

http://{bucket}.s3-website-{region}.amazonaws.com

但它应该是

http://{bucket}.s3-website.{region}.amazonaws.com

注意 websiteregion之间的 .

我最近遇到了这个问题,根本原因似乎是启用了对象版本控制。在桶上禁用版本控制之后,索引 HTML 按预期服务。

我也经历过同样的问题,我用这种方式解决了。 在 S3 Bucket 中,单击 o index.html 复选框,单击 con Actions 选项卡,编辑元数据,你会注意到,在元数据选项中显示“ Type: System Definition,Key: Content-Type,Value: binary/octet-stream”。 更改 价值并输入“ html”并保存更改。 然后点击 index.html,“ Open”按钮。 这招对我管用。

我在从 NodeJS 上传到 S3静态站点时遇到了同样的问题。正如其他人所提到的,这个问题是由于在上传文件时缺少 content-type引起的。当使用 web 界面时,content-type会自动为您应用; 但是,当手动上传时,您需要指定它。中三内容类别一览表.

在 NodeJS 中,您可以像下面这样附加内容类型:

const { extname } = require('path');
const { createReadStream } = require('fs');


// add more types as needed
const getMimeType = ext => {
switch (ext) {
case '.js':
return 'application/javascript';
case '.html':
return 'text/html';
case '.txt':
return 'text/plain';
case '.json':
return 'application/json';
case '.ico':
return 'image/x-icon';
case '.svg':
return 'image/svg+xml';
case '.css':
return 'text/css'
case '.jpg':
case '.jpeg':
return 'image/jpeg';
case '.png':
return 'image/png';
case '.webp':
return 'image/webp';
case '.map':
return 'binary/octet-stream'
default:
return 'application/octet-stream'
}
};


(async() => {
const file = './index.html';
const params = {
Bucket: 'myBucket',
Key: file,
Body: createReadStream(file),
ContentType: getMimeType(extname(file)),
};
await s3.putObject(params).promise();
})();

下面是在设置 content-type 时将目录(包括子目录)上载到 s3的解决方案。

locals {
mime_types = {
".html" = "text/html"
".css" = "text/css"
".js" = "application/javascript"
".ico" = "image/vnd.microsoft.icon"
".jpeg" = "image/jpeg"
".png" = "image/png"
".svg" = "image/svg+xml"
}
}
resource "aws_s3_object" "upload_assets" {
bucket = aws_s3_bucket.www_bucket.bucket
for_each = fileset(var.build_path, "**")
key = each.value
source = "${var.build_path}/${each.value}"
content_type = lookup(local.mime_types, regex("\\.[^.]+$", each.value), null)
etag = filemd5("${var.build_path}/${each.value}")
}

var.build_path是包含您的资产的目录。这一行:

content_type = lookup(local.mime_types, regex("\\.[^.]+$", each.value), null)

通过匹配正则表达式获取文件扩展名,然后使用提供的局部变量映射来查找正确的 content_type

提供者: https://engineering.statefarm.com/blog/terraform-s3-upload-with-mime/