Once you have succesfully created a bucket you can fetch it by name using
Bucket.find.

music_bucket = Bucket.find('jukebox')

The bucket that is returned will contain a listing of all the objects in
the bucket.

music_bucket.objects.size
# => 0

If all you are interested in is the objects of the bucket, you can get to
them directly using Bucket.objects.

Bucket.objects('jukebox').size
# => 0

By default all objects will be returned, though there are several options
you can use to limit what is returned, such as specifying that only objects
whose name is after a certain place in the alphabet be returned, and etc.
Details about these options can be found in the documentation for
Bucket.find.

To add an object to a bucket you specify the name of the object, its value,
and the bucket to put it in.

More about objects and their metadata

You can find out the content type of your object with the
content_type method:

song.content_type
# => "audio/mpeg"

You can change the content type as well if you like:

song.content_type = 'application/pdf'
song.store

(Keep in mind that due to limitiations in S3's exposed API, the only
way to change things like the content_type is to PUT the object onto S3
again. In the case of large files, this will result in fully re-uploading
the file.)

A bevie of information about an object can be had using the about
method:

Streaming uploads

When storing an object on the S3 servers using S3Object.store, the
data argument can be a string or an I/O stream. If data
is an I/O stream it will be read in segments and written to the socket
incrementally. This approach may be desirable for very large files so they
are not read into memory all at once.

This time we didn't have to explicitly pass in the bucket name, as the
JukeBoxSong class knows that it will always use the 'jukebox'
bucket.

“Astute readers”, as they say, may have noticed that we used the third
parameter to pass in the content type, rather than the fourth parameter as
we had the last time we created an object. If the bucket can be inferred,
or is explicitly set, as we've done in the JukeBoxSong class, then the
third argument can be used to pass in options.

Now all operations that would have required a bucket name no longer do.

other_song = JukeBoxSong.find('baby-please-come-home.mp3')

BitTorrent

Another way to download large files

Objects on S3 can be distributed via the BitTorrent file sharing protocol.

You can get a torrent file for an object by calling torrent_for:

S3Object.torrent_for 'kiss.jpg', 'marcel'

Or just call the torrent method if you already have the object:

song = S3Object.find 'kiss.jpg', 'marcel'
song.torrent

Calling grant_torrent_access_to on a object will allow anyone to
anonymously fetch the torrent file for that object:

S3Object.grant_torrent_access_to 'kiss.jpg', 'marcel'

Anonymous requests to

http://s3.amazonaws.com/marcel/kiss.jpg?torrent

will serve up the torrent file for that object.

Access control

Using canned access control policies

By default buckets are private. This means that only the owner has access
rights to the bucket and its objects. Objects in that bucket inherit the
permission of the bucket unless otherwise specified. When an object is
private, the owner can generate a signed url that exposes the object to
anyone who has that url. Alternatively, buckets and objects can be given
other access levels. Several canned access levels are defined:

:private - Owner gets FULL_CONTROL. No one else has any access
rights. This is the default.

:public_read - Owner gets FULL_CONTROL and the anonymous principal
is granted READ access. If this policy is used on an object, it can be read
from a browser with no authentication.

:public_read_write - Owner gets FULL_CONTROL, the anonymous
principal is granted READ and WRITE access. This is a useful policy to
apply to a bucket, if you intend for any anonymous user to PUT objects into
the bucket.

Policies are made up of one or more grants which grant a specific
permission to some grantee. Here we see the default FULL_CONTROL grant to
the owner of this object. There is also READ permission granted to the
Allusers Group, which means anyone has read access for the object.

Say we wanted to grant access to anyone to read the access policy of this
object. The current READ permission only grants them permission to read
the object itself (for example, from a browser) but it does not allow them
to read the access policy. For that we will need to grant the AllUsers
group the READ_ACP permission.

There are three ways to specify a grantee: 1) by their internal amazon id,
such as the one returned with an object's Owner, 2) by their Amazon
account email address or 3) by specifying a group. As of this writing you
can not create custom groups, but Amazon does provide three already:
AllUsers, Authenticated and LogDelivery. In this case we want to provide
the grant to all users. This effectively means “anyone”.

Pre-prepared grants

Alternatively, the ACL::Grant class defines a set of stock grant policies
that you can fetch by name. In most cases, you can just use one of these
pre-prepared grants rather than building grants by hand. Two of these stock
policies are :public_read and :public_read_acp, which
happen to be the two grants that we built by hand above. In this case we
could have simply written:

Logging

Tracking requests made on a bucket

A bucket can be set to log the requests made on it. By default logging is
turned off. You can check if a bucket has logging enabled:

Bucket.logging_enabled_for? 'jukebox'
# => false

Enabling it is easy:

Bucket.enable_logging_for('jukebox')

Unless you specify otherwise, logs will be written to the bucket you want
to log. The logs are just like any other object. By default they will start
with the prefix 'log-'. You can customize what bucket you want the
logs to be delivered to, as well as customize what the log objects' key
is prefixed with by setting the target_bucket and
target_prefix option:

Errors

When things go wrong

Anything you do that makes a request to S3 could result in an error. If it
does, the AWS::S3 library will raise an exception specific to the error.
All exception that are raised as a result of a request returning an error
response inherit from the ResponseError exception. So should you choose to
rescue any such exception, you can simple rescue ResponseError.

Once you've captured the exception, you can extract the error message
from S3, as well as the full error response, which includes things like
the HTTP response code:

error
# => #<AWS::S3::BucketNotEmpty The bucket you tried to delete is not empty>
error.message
# => "The bucket you tried to delete is not empty"
error.response.code
# => 409

You could use this information to redisplay the error in a way you see fit,
or just to log the error and continue on.

Accessing the last request's response

Sometimes methods that make requests to the S3 servers return some object,
like a Bucket or an S3Object. Othertimes they return just true.
Other times they raise an exception that you may want to rescue. Despite
all these possible outcomes, every method that makes a request stores its
response object for you in Service.response. You can always get to the
last request's response via Service.response.