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

基于Boto3重构Tornado API以获取指定路径的AWS S3桶内容

用Boto3实现原Boto S3内容列表功能的解决方案

我懂你现在的困扰——原Boto代码能精准返回你想要的结构,但换成Boto3后总是拿到带全路径的对象列表,没法直接复用原有逻辑。别担心,我帮你把原代码的核心逻辑1:1转换成Boto3版本,还会拆解关键差异点。

先梳理下你原Boto代码的核心逻辑:

  • 基于传入的path和bucket_name,用/作为分隔符模拟目录结构,列出指定路径下的“文件夹”和文件
  • 跳过与当前path完全一致的条目
  • 区分文件夹(以/结尾)和文件,分别提取截掉path前缀后的文件名、类型、格式化后的大小
  • 组装成指定结构的响应返回

在Boto3里,对应的API是list_objects_v2,关键是要正确设置Prefix和Delimiter参数,这样才能得到和原Botobucket.list(path, "/")一样的“目录视图”,而不是返回所有前缀匹配的对象。下面是转换后的完整代码:

import boto3
from botocore.exceptions import ClientError
import json

def post(self):
    try:
        resp = []
        path = self.get_argument('path')
        bucket_name = self.get_argument('bucket_name')
        path_len = len(path)
        
        # 初始化Boto3 S3客户端(需指定区域可添加region_name参数,比如region_name='us-west-2')
        s3_client = boto3.client('s3')
        
        # 用分页器处理大量对象场景,自动处理分页逻辑
        paginator = s3_client.get_paginator('list_objects_v2')
        response_iterator = paginator.paginate(
            Bucket=bucket_name,
            Prefix=path,
            Delimiter='/'
        )
        
        for page in response_iterator:
            # 处理模拟的"文件夹"(Boto3中用CommonPrefixes返回)
            if 'CommonPrefixes' in page:
                for prefix in page['CommonPrefixes']:
                    folder_name = prefix['Prefix']
                    if folder_name == path:
                        continue
                    # 截取path之后的文件夹名,去掉末尾的/
                    file_name = folder_name[path_len:-1]
                    resp.append({
                        "bucket": bucket_name,
                        "path": path,
                        "name": file_name,
                        "type": 'd',
                        "size": ""
                    })
            
            # 处理实际文件对象(Boto3中用Contents返回)
            if 'Contents' in page:
                for obj in page['Contents']:
                    obj_name = obj['Key']
                    if obj_name == path:
                        continue
                    # 截取path之后的文件名
                    file_name = obj_name[path_len:]
                    _file_size = self.filesize(obj['Size'])
                    resp.append({
                        "bucket": bucket_name,
                        "path": path,
                        "name": file_name,
                        "type": 'f',
                        "size": _file_size
                    })
        
        self.write(json.dumps(resp))
    except ClientError as e:
        # 可根据需求添加错误处理逻辑,比如返回500状态码
        self.set_status(500)
        self.write(json.dumps({"error": str(e)}))
    except Exception as e:
        self.set_status(500)
        self.write(json.dumps({"error": str(e)}))

关键细节说明:

  • 分页处理:Boto3的list_objects_v2默认最多返回1000个对象,用paginator自动处理分页,避免遗漏内容(原Boto的bucket.list()其实也自动分页,只是隐藏了细节)。
  • 文件夹与文件区分:Boto3通过CommonPrefixes返回模拟的文件夹(以/结尾的前缀),通过Contents返回实际文件对象,完全对应原代码的区分逻辑。
  • 区域兼容:Boto3客户端会通过AWS配置链自动识别桶的区域,若需强制指定,可在初始化时添加region_name参数,解决原代码在部分区域桶失效的问题。
  • 文件名截取:和原代码逻辑完全一致,文件夹去掉末尾的/,文件直接截取path后的部分,保证返回结构和原代码完全相同。

这样转换后,返回的resp结构和原Boto代码完全一致,应该能解决你之前遇到的全路径问题,同时兼容不同区域的桶。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 10:18:55