S3 boto列表键有时会返回目录键

时间:2012-03-31 09:03:34

标签: python amazon-s3 amazon-web-services boto

我注意到boto的api返回值取决于存储桶位置。我有以下代码:

con = S3Connection(AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY)
bucket = con.get_bucket(S3_BUCKET_NAME)
keys = bucket.list(path)
for key in keys:
  print key

我在两个桶中运行,一个在美国西部,一个在爱尔兰。这个桶中的路径是一个子目录,对爱尔兰我得到子目录和下面的任何键,对我们西方我只得到下面的键。

所以爱尔兰给出了:

<Key: <bucketName>,someDir/>
<Key: <bucketName>,someDir/someFile.jpg>
<Key: <bucketName>,someDir/someOtherFile.jpg>

美国标准给出的地方:

<Key: <bucketName>,someDir/someFile.jpg>
<Key: <bucketName>,someDir/someOtherFile.jpg>

显然,无论存储桶位置如何,我都希望能够编写相同的代码。任何人都知道我可以做些什么来解决这个问题,所以我得到了同样可预测的结果。或者即使它导致问题或S3。我注意到在爱尔兰有一个不同的命名桶的政策,不同的当地人有自己的api版本吗?

谢谢,

史蒂夫

5 个答案:

答案 0 :(得分:18)

感谢Steffen,他建议查看如何创建密钥。经过进一步的调查,我想我已经掌握了这里发生的事情。我与水桶区域相连的原始位置是红鲱鱼。它似乎是由于操作密钥时管理控制台的作用。

如果在管理控制台中创建目录,则会创建一个0字节密钥。执行列表时将返回此信息。

如果您使用boto创建/上传文件,则它不会创建该文件夹。有趣的是,如果从文件夹中删除文件(从AWS控制台),则会为用于包含密钥的文件夹创建密钥。如果您然后使用boto再次上传bey,那么您在UI中具有完全相同的外观结构,但实际上您有一个虚假的附加密钥用于该目录。这就是我发生的事情,因为我正在测试我的应用程序,我正在清理密钥然后找到不同的结果。

值得知道这种情况发生。 UI中没有指示器显示文件夹是创建文件夹(一个将作为键返回)还是解释文件夹(基于键名称)。

答案 1 :(得分:6)

我对你的问题没有明确的答案,但至少可以抛出一些部分答案:

背景

目录/文件夹模拟

Amazon S3实际上没有文件夹/目录的原生概念,而是仅由桶和对象/键组成的平面存储架构 - 在S3的大多数工具中看到的目录样式表示(包括{ {3}}本身完全基于约定,即模拟具有相同前缀的对象的层次结构 - 有关此体系结构的更多详细信息,请参阅我对AWS Management Console的回答,包括来自AWS文档的引用/引用。

每个区域的API差异

  

我注意到在爱尔兰有一个不同的命名桶的政策,   不同的当地人有自己的api版本吗?

How to specify an object expiration prefix that doesn't match the directory?显然确实如此,这是他们最早的产品之一,例如Amazon S3

  

在除<美国标准区域之外的所有地区,您必须使用   命名存储桶时遵循以下准则。 [...] [强调我的]

美国标准区域的这些细节也可以在Bucket Restrictions and Limitations的其他地方看到,而美国标准本身就是一个不寻常的结构。否则明显受地理限制S3 documentation

  

美国标准 - 在美国使用Amazon S3服务器

     

这是默认区域。 自动显示美国标准区域   将请求路由到北弗吉尼亚州或太平洋地区的设施   西北航空使用网络地图。要使用此区域,请选择美国标准   作为在控制台中创建存储桶时的区域。美国标准   Region为所有请求提供最终一致性。 [强调我的]

此隐式CDN行为对于此默认区域的S3(即美国标准)是唯一的,而在我认为的任何其他AWS服务上的其他地方都看不到。

可能的原因

我有一个微弱的S3内存实际上将零字节对象/密钥放入更近期区域的模拟目录/文件夹的存储桶中(即除了美国标准之外),而传统的解决方案对于美国标准区域可能会有所不同,例如,仅仅基于已建立的/目录分隔的命名约定,并且完全省略了专用对象/密钥。

解决方案

如果分析是正确的,除了为两种情况维护单独的代码路径之外,你无能为力,我担心

祝你好运!

答案 2 :(得分:5)

我遇到了同样的问题。作为解决方法,您可以使用尾随'/'过滤掉所有键,以消除“目录”条目。

def files(keys):
    return (key for key in keys if not key.name.endswith('/'))

s3 = boto.connect_s3(AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY)
bucket = s3.get_bucket(S3_BUCKET_NAME)
keys = bucket.list(path)
for key in files(keys):
    print(key)

答案 3 :(得分:0)

我正在使用“文件夹”没有“。”的事实。在它的道路上。 一个文件。 媒体/图像不会被删除 media / images / sample.jpg将被删除

e.g。清理存储桶文件

def delete_all_bucket_files(self,bucket_name):
        bucket = self.get_bucket(bucket_name)
        if bucket:
            for key in bucket.list():
                #delete only the files, not the folders
                if period_char in key.name:
                    print 'deleting: ' + key.name
                    key.delete()

答案 4 :(得分:0)

您可以使用 size 参数来排除前缀:

for key in keys: 
  if key.size > 0:
  print key