如何在S3中公开10,000个文件


92

我在一个装有10,000个文件的存储桶中有一个文件夹。似乎没有办法将其上传并立即将其公开。所以我全部上传了,它们是私人的,我需要将它们全部公开。

我已经尝试过aws控制台,它只是给出了一个错误(适用于文件较少的文件夹)。

我已经尝试过在Firefox中使用S3整理功能。

是否可以运行某些软件或脚本来公开所有这些信息?


4
我尝试使用的每个工具都崩溃了,所以我最终写了一个PHP脚本,该脚本花费了几个小时,并且循环访问了存储桶中的每个对象并将其公开。
PeterV

Answers:


119

您可以生成存储桶策略(请参见下面的示例),该策略可以访问存储桶中的所有文件。可以通过AWS控制台将存储桶策略添加到存储桶。

{
    "Id": "...",
    "Statement": [ {
        "Sid": "...",
        "Action": [
            "s3:GetObject"
        ],
        "Effect": "Allow",
        "Resource": "arn:aws:s3:::bucket/*",
        "Principal": {
            "AWS": [ "*" ]
        }
    } ]
}

另请参阅以下由Amazon提供的策略生成器工具。

http://awspolicygen.s3.amazonaws.com/policygen.html


5
这对我没有用。即使使用了存储桶策略,某些对象仍会返回“拒绝访问”响应。它是从上面复制粘贴的,只是存储桶名称已更改。我想是时候编写一个脚本来循环遍历所有130万个对象了……有点令人不快
Blake Miller

您需要将“ bucket”更改为您的存储桶的名称
karnage 2012年

11
我很讨厌这种方式。那是一些丑陋的JSON。
superluminary

6
仅需注意:这似乎很明显,但是您也可以选择限制对特定文件夹的访问:bucket/avatars/*。(别忘了*最后。我做到了,我转了
一圈

2
@Benjamin对于您来说,什么是“基本”配置不适合其他人使用,因为每个人的安全要求都不同。AWS提供了一种统一的方式来定制这些策略。因此,必须花一些时间正确学习安全策略,并且不要回避几行简单的JSON。
afilina

69

如果是第一次上传,则可以在命令行上将文件设置为在上传时公开:

aws s3 sync . s3://my-bucket/path --acl public-read

如在AWS命令行界面使用高级s3命令中所述

不幸的是,仅在文件上传时才应用ACL。它没有(在我的测试中)将ACL应用于已上传的文件。

如果您确实想更新现有对象,则可以将存储桶与其自身同步,但这似乎已停止工作。

[不再工作]可以从命令行完成:

aws s3 sync s3://my-bucket/path s3://my-bucket/path --acl public-read

(因此,它不再回答问题,而是保留以前的答案以供参考。)


该命令对已经上传但尚未公开读取的文件有效吗?
Alston

10
当我测试它时,似乎只将ACL添加到新同步的文件中。
大卫·罗素

谢谢您重播,我也对其进行了测试。有什么方法可以批量更改上载文件的权限?
阿斯顿(Alston)2013年

哦,难怪。我对此感到困惑。非常感谢您的澄清。
Sridhar Sarnobat '16

答案已更新,包括如何更改现有文件。
大卫·罗素

34

我不得不更换数十万个对象。我启动了一个EC2实例来运行它,这使一切运行得更快。您需要先安装aws-sdkgem。

这是代码:

require 'rubygems'
require 'aws-sdk'


# Change this stuff.
AWS.config({
    :access_key_id => 'YOURS_HERE',
    :secret_access_key => 'YOURS_HERE',
})
bucket_name = 'YOUR_BUCKET_NAME'


s3 = AWS::S3.new()
bucket = s3.buckets[bucket_name]
bucket.objects.each do |object|
    puts object.key
    object.acl = :public_read
end

1
一种简单的方法是首先将它们设置为public_read标记,但是如果失败,这是一个不错的选择。
superluminary

这段代码已过时,请参阅我的答案
ksarunas

26

我遇到了同样的问题,由于新版本的SDK出现了,@ DanielVonFange的解决方案已过时。

现在添加适用于我的AWS Ruby SDK的代码段:

require 'aws-sdk'

Aws.config.update({
  region: 'REGION_CODE_HERE',
  credentials: Aws::Credentials.new(
    'ACCESS_KEY_ID_HERE',
    'SECRET_ACCESS_KEY_HERE'
  )
})
bucket_name = 'BUCKET_NAME_HERE'

s3 = Aws::S3::Resource.new
s3.bucket(bucket_name).objects.each do |object|
  puts object.key
  object.acl.put({ acl: 'public-read' })
end

1
很棒的

@ksarunas在我的情况下,我需要将public更改为private权限,因此将public-read替换为private并更改访问权限,但是仍然可以访问URL?
拉胡尔

19

只是想使用新的S3控制台添加它,您可以选择您的文件夹,然后选择Make public将文件夹中的所有文件公开。它用作后台任务,因此应处理任意数量的文件。

公之于众


5
不幸的是,这花费了很长时间,并且在运行命令时您无法关闭浏览器。您的浏览器为每个文件发送2个请求,以我为例,两个请求耗时500毫秒。如果您有很多文件,则需要花费很长时间=(
Herlon Aguiar

2
而且,还有另一个问题:这将完全公开。如果您只想公开读取访问权限,那就是一个问题。
MarceloAgimóvel18年

一定要注意-我这样做是“公开”的,并且弹出的“进度条”非常微妙,我认为已经完成了。我检查了一下并可能花了一个小时进行研究,然后才意识到您单击“公开”,然后出现一个细微的“进度条显示” ... grrr ...因为我关闭了浏览器窗口约10次,所以我假设每次都将其杀死。我现在正在运行它-非常快-可能需要20分钟才能获得12万张图像
Scott

11

使用cli:

aws s3 ls s3://bucket-name --recursive > all_files.txt && grep .jpg all_files.txt > files.txt && cat files.txt | awk '{cmd="aws s3api put-object-acl --acl public-read --bucket bucket-name --key "$4;system(cmd)}'


3
您不能只使用管道进行grep而不是将所有files.txt写入磁盘吗?这可以是aws s3 ls s3://bucket-name --recursive | grep .jpg | awk '{cmd="aws s3api put-object-acl --acl public-read --bucket bucket-name --key "$4;system(cmd)}'
sakurashinken

3

如果我自己有这个需要,但是文件的数量使其在串行处理中变得很慢。所以我写了一个脚本iron.ioIronWorker上执行服务。他们每月有500个免费的计算小时,足以应付更多的工作量(如果您超过这个价格,这是合理的)。由于它是并行完成的,因此对于我拥有的32,000个对象,它不到一分钟即可完成。我也相信他们的服务器在EC2上运行,因此作业和S3之间的通信很快。

欢迎任何人根据自己的需要使用我的脚本。


2

看看BucketExplorer,它可以很好地管理批量操作,并且是可靠的S3客户端。


3
现在,还可以通过信息面板在Cyber​​duck中批量更改权限(免费)。
Taylor Edmiston 2014年

BucketExplorer仅在您有权列出所有存储桶时才有用。最好使用CLI或SDK进行此操作,并使用户具有受限权限。
–perilandmishap

0

您会认为他们会公开读取默认行为,不是吗?:)在构建自定义API以通过C#解决方案与S3交互时,我分享了您的无奈。这是完成S3对象的上传并将其默认设置为公共读取访问的代码段:

public void Put(string bucketName, string id, byte[] bytes, string contentType, S3ACLType acl) {
     string uri = String.Format("https://{0}/{1}", BASE_SERVICE_URL, bucketName.ToLower());
     DreamMessage msg = DreamMessage.Ok(MimeType.BINARY, bytes);
     msg.Headers[DreamHeaders.CONTENT_TYPE] = contentType;
     msg.Headers[DreamHeaders.EXPECT] = "100-continue";
     msg.Headers[AWS_ACL_HEADER] = ToACLString(acl);
     try {
        Plug s3Client = Plug.New(uri).WithPreHandler(S3AuthenticationHeader);
        s3Client.At(id).Put(msg);
     } catch (Exception ex) {
        throw new ApplicationException(String.Format("S3 upload error: {0}", ex.Message));
     }
}

ToACLString(acl)函数返回public-read,BASE_SERVICE_URL是s3.amazonaws.com,而AWS_ACL_HEADER常量是x-amz-acl。当我们使用Dream框架简化我们的http通信时,plug和DreamMessage的东西对您来说可能看起来很奇怪。本质上,我们正在按照每个AWS规范执行具有指定标头和特殊标头签名的http PUT(请参阅AWS文档中的此页面)有关如何构造授权标头的示例,)。

要更改现有的1000个对象ACL,您可以编写脚本,但是使用GUI工具解决当前问题可能更容易。到目前为止,我使用过的最好的软件来自一家名为S3的cloudberry公司。看来他们至少有一种产品可以免费试用15天。我刚刚验证过,它将允许您一次选择多个对象,并通过上下文菜单将其ACL设置为public。享受云!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.