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

我桶里有个文件夹,里面有一万个文件。似乎没有办法将它们上传并立即公开。所以我把它们都上传了,它们是私人的,我需要把它们都公开。

我已经尝试了 aws 控制台,它只是给出了一个错误(对于文件较少的文件夹可以很好地工作)。

我试过在 Firefox 中使用 S3组织,也是同样的道理。

是否有一些软件或脚本,我可以运行,使所有这些公开?

60232 次浏览

Have a look at BucketExplorer it manages bulk operations very well and is a solid S3 Client.

You would think they would make public read the default behavior, wouldn't you? : ) I shared your frustration while building a custom API to interface with S3 from a C# solution. Here is the snippet that accomplishes uploading an S3 object and setting it to public-read access by default:

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));
}
}

The ToACLString(acl) function returns public-read, BASE_SERVICE_URL is s3.amazonaws.com and the AWS_ACL_HEADER constant is x-amz-acl. The plug and DreamMessage stuff will likely look strange to you as we're using the Dream framework to streamline our http communications. Essentially we're doing an http PUT with the specified headers and a special header signature per aws specifications (see this page in the aws docs for examples of how to construct the authorization header).

To change an existing 1000 object ACLs you could write a script but it's probably easier to use a GUI tool to fix the immediate issue. The best I've used so far is from a company called cloudberry for S3; it looks like they have a free 15 day trial for at least one of their products. I've just verified that it will allow you to select multiple objects at once and set their ACL to public through the context menu. Enjoy the cloud!

You can generate a bucket policy (see example below) which gives access to all the files in the bucket. The bucket policy can be added to a bucket through AWS console.

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

Also look at following policy generator tool provided by Amazon.

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

I had to change several hundred thousand objects. I fired up an EC2 instance to run this, which makes it all go faster. You'll want to install the aws-sdk gem first.

Here's the code:

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

Had this need myself but the number of files makes it WAY to slow to do in serial. So I wrote a script that does it on iron.io's IronWorker service. Their 500 free compute hours per month are enough to handle even large buckets (and if you do exceed that the pricing is reasonable). Since it is done in parallel it completes in less than a minute for the 32,000 objects I had. Also I believe their servers run on EC2 so the communication between the job and S3 is quick.

Anybody is welcome to use my script for their own needs.

I had the same problem, solution by @DanielVonFange is outdated, as new version of SDK is out.

Adding code snippet that works for me right now with 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

If you are uploading for the first time, you can set the files to be public on upload on the command line:

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

As documented in Using High-Level s3 Commands with the AWS Command Line Interface

Unfortunately it only applies the ACL when the files are uploaded. It does not (in my testing) apply the ACL to already uploaded files.

If you do want to update existing objects, you used to be able to sync the bucket to itself, but this seems to have stopped working.

[Not working anymore] This can be done from the command line:

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

(So this no longer answers the question, but leaving answer for reference as it used to work.)

Just wanted to add that with the new S3 Console you can select your folder(s) and select Make public to make all files inside the folders public. It works as a background task so it should handle any number of files.

Make Public

Using the 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)}'

If your filenames have spaces, we can take Alexander Vitanov's answer above and run it through jq:

#!/bin/bash
# make every file public in a bucket example
bucket=www.example.com
IFS=$'\n' && for tricky_file in $(aws s3api list-objects --bucket "${bucket}" | jq -r '.Contents[].Key')
do
echo $tricky_file
aws s3api put-object-acl --acl public-read --bucket "${bucket}" --key "$tricky_file"
done