You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

通过Boto3为AWS静态网站文件设置正确内容类型的方法

刚好我在部署AWS静态网站时也遇到过同样的问题,来给你详细解答下~

一、AWS静态网站常见文件的正确Content-Type

浏览器会根据Content-Type值来决定如何解析文件,设置正确的类型是静态网站正常渲染的关键,常见文件对应的类型如下:

  • HTML文件:text/html(你的代码里已经用对了)
  • CSS样式文件:text/css
  • JavaScript脚本:application/javascript(现在官方推荐这个,替代旧的text/javascript
  • PNG图片:image/png
  • JPG/JPEG图片:image/jpeg
  • SVG矢量图:image/svg+xml
  • WebP图片:image/webp
  • WOFF2字体:font/woff2
  • TTF字体:font/ttf
  • JSON数据文件:application/json
  • 纯文本文件:text/plain
二、用Boto3的upload_file智能设置Content-Type

你之前没加ExtraArgs时出现异常,是因为S3默认会把所有上传文件的Content-Type设为binary/octet-stream,浏览器拿到这个类型会直接触发下载,而不是渲染HTML内容,所以必须手动指定正确的类型。

要实现智能设置,不用手动给每个文件写类型,可以用Python自带的mimetypes模块,它能根据文件扩展名自动识别对应的MIME类型。

单个文件上传的改进代码

import boto3
import mimetypes

# 初始化S3资源
s3 = boto3.resource('s3')
bucket = s3.Bucket('allecijfers.nl')

# 本地文件路径和S3目标路径
local_file = 'C:/Hugo/Sites/allecijfers/public/test/index.html'
s3_key = 'test/index.html'

# 自动识别文件的Content-Type
content_type, _ = mimetypes.guess_type(local_file)
# 防止识别失败,设置默认值
if not content_type:
    content_type = 'application/octet-stream'

# 上传并自动设置Content-Type和访问权限
bucket.upload_file(
    local_file,
    s3_key,
    ExtraArgs={
        'ACL': 'public-read',
        'ContentType': content_type
    }
)

批量上传整个目录(适合Hugo生成的静态站点)

如果要上传Hugo生成的整个public目录,写个遍历函数就能自动处理所有文件的类型:

import boto3
import mimetypes
import os

s3 = boto3.resource('s3')
bucket = s3.Bucket('allecijfers.nl')

def upload_static_site(local_dir, s3_root_prefix=''):
    """批量上传本地静态目录到S3"""
    # 手动补充一些mimetypes识别不到的小众类型
    mimetypes.add_type('image/webp', '.webp')
    mimetypes.add_type('font/woff2', '.woff2')
    
    for root, _, files in os.walk(local_dir):
        for file in files:
            local_path = os.path.join(root, file)
            # 计算S3上的相对路径(处理Windows路径分隔符)
            relative_path = os.path.relpath(local_path, local_dir).replace('\\', '/')
            s3_key = os.path.join(s3_root_prefix, relative_path)
            
            # 自动获取Content-Type
            content_type, _ = mimetypes.guess_type(local_path)
            content_type = content_type or 'application/octet-stream'
            
            # 上传文件
            bucket.upload_file(
                local_path,
                s3_key,
                ExtraArgs={
                    'ACL': 'public-read',
                    'ContentType': content_type
                }
            )
            print(f"✅ 上传完成: {s3_key} | Content-Type: {content_type}")

# 调用函数,把Hugo的public目录上传到S3根目录
upload_static_site('C:/Hugo/Sites/allecijfers/public')

补充说明

  • mimetypes.guess_type基本能覆盖绝大多数常见文件类型,但如果遇到一些小众格式,可以用mimetypes.add_type()手动添加映射。
  • 上传时一定要设置ACL: 'public-read',否则静态网站的访问者会因为权限不足无法加载文件。

内容的提问来源于stack exchange,提问作者Wouter

火山引擎 最新活动