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

如何追踪使用Python SDK的Presigned POST上传AWS S3的进度?

嘿,我之前也碰到过这个问题!用Presigned POST上传S3的时候,boto3确实没有内置的进度追踪钩子,但我们可以在发送POST请求的环节自己实现,核心思路就是在文件上传过程中统计已发送的字节数,进而计算进度。

追踪S3 Presigned POST上传进度的实现方法

Presigned POST本质是构造一个带签名的表单,再通过HTTP POST请求把文件传到S3,所以我们只需要在发送这个请求的步骤里,给文件读取过程加上进度监听逻辑就行。下面是具体的实现步骤:

1. 先生成Presigned POST表单

这部分和你之前的代码逻辑一致,用boto3生成带签名的上传表单:

import boto3
from botocore.exceptions import ClientError

s3_client = boto3.client('s3')

def create_presigned_post(bucket_name, object_name, fields=None, conditions=None, expiration=3600):
    try:
        response = s3_client.generate_presigned_post(
            bucket_name,
            object_name,
            Fields=fields,
            Conditions=conditions,
            ExpiresIn=expiration
        )
    except ClientError as e:
        print(f"生成Presigned POST失败: {e}")
        return None
    return response

2. 定义进度追踪的回调函数

写一个简单的回调函数,用来接收已上传字节数和总字节数,计算并打印进度:

def upload_progress_callback(uploaded_bytes, total_bytes):
    progress_percent = (uploaded_bytes / total_bytes) * 100
    # 用\r实现进度条刷新效果
    print(f"上传进度: {progress_percent:.2f}% ({uploaded_bytes}/{total_bytes} 字节)", end='\r')

3. 包装文件对象并发送POST请求

这里用requests库来发送请求(比自带的urllib更灵活),我们需要自定义一个文件类,在每次读取文件块的时候触发进度回调:

import os
import requests

class ProgressTrackingFile:
    def __init__(self, file_obj, total_size, callback):
        self.file_obj = file_obj
        self.total_size = total_size
        self.callback = callback
        self.uploaded = 0

    def read(self, chunk_size=1024*1024):  # 按1MB块读取
        data = self.file_obj.read(chunk_size)
        if data:
            self.uploaded += len(data)
            self.callback(self.uploaded, self.total_size)
        return data

然后用这个类包装你的文件,再发送Presigned POST请求:

# 生成上传表单
presigned_post = create_presigned_post('你的存储桶名称', '要上传的对象键')
if not presigned_post:
    exit("无法生成Presigned POST表单")

# 准备要上传的文件
file_path = '/path/to/your/file'
total_file_size = os.path.getsize(file_path)

with open(file_path, 'rb') as f:
    # 包装文件对象,绑定进度回调
    tracked_file = ProgressTrackingFile(f, total_file_size, upload_progress_callback)
    # 发送POST请求
    response = requests.post(
        presigned_post['url'],
        data=presigned_post['fields'],
        files={'file': tracked_file}
    )

# 检查上传结果
if response.status_code == 204:
    print("\n上传完成!")
else:
    print(f"\n上传失败,状态码: {response.status_code},响应内容: {response.text}")

进阶:用tqdm实现美观的进度条

如果觉得自己打印进度不够好看,可以用tqdm库快速实现带样式的进度条:

from tqdm import tqdm

# 初始化进度条
progress_bar = tqdm(total=total_file_size, unit='B', unit_scale=True, desc="上传中")

def tqdm_progress_callback(uploaded_bytes, total_bytes):
    # 更新进度条到当前已上传字节数
    progress_bar.update(uploaded_bytes - progress_bar.n)

# 后续步骤和之前一样,只是把回调换成这个tqdm的版本

这个方法完全基于boto3和requests,不需要额外的S3相关依赖,而且能精准追踪每一块文件的上传进度,亲测有效!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 08:45:02