You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Python向Amazon S3预签名URL上传文件

S3预签名URL上传问题解答

核心结论

  • 你当前生成的是get_object操作类型的预签名URL,仅支持S3对象下载,无法直接用于上传文件
  • 要通过预签名URL实现上传,需要先生成put_object操作类型的专用预签名URL,再通过HTTP PUT请求提交文件即可

具体实现步骤

步骤1:生成上传专用预签名URL

修改原有生成逻辑,将客户端操作类型从get_object替换为put_object即可:

import logging
import boto3
from botocore.exceptions import ClientError

def create_presigned_upload_url(bucket_name, object_name, expiration=3600):
    """生成用于S3对象上传的预签名URL
    :param bucket_name: S3桶名称
    :param object_name: 上传后在S3存储中的对象键(文件路径/名称)
    :param expiration: URL有效期,单位为秒,默认1小时
    :return: 预签名URL字符串,生成失败返回None
    """
    s3_client = boto3.client('s3')
    try:
        response = s3_client.generate_presigned_url(
            ClientMethod='put_object',
            Params={'Bucket': bucket_name, 'Key': object_name},
            ExpiresIn=expiration
        )
    except ClientError as e:
        logging.error(e)
        return None
    return response

# 调用示例:生成上传到bucket123、对象键为upload_test.txt的预签名URL
upload_url = create_presigned_upload_url("bucket123", "upload_test.txt")

步骤2:使用预签名URL上传本地文件

可以借助requests库发起PUT请求完成上传,如未安装依赖可先执行pip install requests:

import requests
import logging

def upload_file_with_presigned_url(presigned_url, local_file_path):
    """通过预签名URL上传本地文件
    :param presigned_url: 步骤1生成的上传专用预签名URL
    :param local_file_path: 本地待上传文件的完整路径
    :return: 上传成功返回True,失败返回False
    """
    try:
        with open(local_file_path, 'rb') as file:
            response = requests.put(presigned_url, data=file)
        # 状态码为200代表上传成功
        response.raise_for_status()
        return True
    except Exception as e:
        logging.error(f"上传失败: {str(e)}")
        return False

# 调用示例:上传本地路径下的local_test.txt文件
upload_status = upload_file_with_presigned_url(upload_url, "./local_test.txt")

注意事项

  • 生成预签名URL的身份凭证必须拥有对应S3桶的s3:PutObject权限,否则上传时会返回403错误
  • 上传请求必须使用PUT方法,使用POST/GET方法都会触发签名校验失败
  • 预签名URL过期后无法继续使用,需要重新生成
  • 如果上传时需要指定Content-Type等头参数,生成预签名URL时也需要在Params中传入对应参数,否则会出现签名不匹配错误。例如需要指定上传文本文件时,生成URL的Params需要改为{'Bucket': bucket_name, 'Key': object_name, 'ContentType': 'text/plain'},同时上传请求也要带上对应的Content-Type: text/plain请求头。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 12:24:09