aws-s3 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/INSTALL +5 -1
- data/README +20 -14
- data/Rakefile +1 -0
- data/lib/aws/s3.rb +3 -6
- data/lib/aws/s3/acl.rb +1 -1
- data/lib/aws/s3/base.rb +1 -2
- data/lib/aws/s3/bucket.rb +2 -5
- data/lib/aws/s3/object.rb +30 -9
- data/lib/aws/s3/version.rb +3 -3
- data/test/object_test.rb +16 -0
- data/test/remote/object_test.rb +27 -0
- metadata +10 -1
data/INSTALL
CHANGED
@@ -38,4 +38,8 @@ If your system has the Ruby libxml bindings installed (http://libxml.rubyforge.o
|
|
38
38
|
|
39
39
|
=== XML generation
|
40
40
|
|
41
|
-
AWS::S3 also depends on the Builder library (http://builder.rubyforge.org/ and http://rubyforge.org/projects/builder/). This will also automatically be installed for you when using Rubygems.
|
41
|
+
AWS::S3 also depends on the Builder library (http://builder.rubyforge.org/ and http://rubyforge.org/projects/builder/). This will also automatically be installed for you when using Rubygems.
|
42
|
+
|
43
|
+
=== Content type inference
|
44
|
+
|
45
|
+
AWS::S3 depends on the MIME::Types library (http://mime-types.rubyforge.org/) to infer the content type of an object that does not explicitly specify it. This library will automatically be installed for you when using Rubygems.
|
data/README
CHANGED
@@ -96,12 +96,9 @@ To add an object to a bucket you specify the name of the object, its value, and
|
|
96
96
|
S3Object.store(
|
97
97
|
file,
|
98
98
|
File.open(file),
|
99
|
-
'jukebox'
|
100
|
-
:content_type => 'audio/mpeg'
|
99
|
+
'jukebox'
|
101
100
|
)
|
102
101
|
|
103
|
-
Though strictly not required, you should specify the content type of the file so that when you go to download it your browser will know how to handle the file.
|
104
|
-
|
105
102
|
You'll see your file has been added to it:
|
106
103
|
|
107
104
|
music_bucket.objects
|
@@ -135,8 +132,20 @@ You can store an object on S3 by specifying a key, its data and the name of the
|
|
135
132
|
S3Object.store(
|
136
133
|
'headshot.jpg',
|
137
134
|
File.open('headshot.jpg'),
|
138
|
-
'photos'
|
139
|
-
|
135
|
+
'photos'
|
136
|
+
)
|
137
|
+
|
138
|
+
The content type of the object will be infered by its extension. If the appropriate content type can not be infered, S3 defaults
|
139
|
+
to <tt>binary/octect-stream</tt>.
|
140
|
+
|
141
|
+
If you want to override this, you can explicitly indicate what content type the object should have with the <tt>:content_type</tt> option:
|
142
|
+
|
143
|
+
file = 'black-flowers.m4a'
|
144
|
+
S3Object.store(
|
145
|
+
file,
|
146
|
+
File.open(file),
|
147
|
+
'jukebox',
|
148
|
+
:content_type => 'audio/mp4a-latm'
|
140
149
|
)
|
141
150
|
|
142
151
|
You can read more about storing files on S3 in the documentation for S3Object.store.
|
@@ -188,7 +197,7 @@ You can find out the content type of your object with the <tt>content_type</tt>
|
|
188
197
|
|
189
198
|
You can change the content type as well if you like:
|
190
199
|
|
191
|
-
song.content_type = 'application/
|
200
|
+
song.content_type = 'application/pdf'
|
192
201
|
song.store
|
193
202
|
|
194
203
|
(Keep in mind that due to limitiations in S3's exposed API, the only way to change things like the content_type
|
@@ -240,14 +249,12 @@ may be desirable for very large files so they are not read into memory all at on
|
|
240
249
|
# Non streamed upload
|
241
250
|
S3Object.store('simple-text-file.txt',
|
242
251
|
'hello world!',
|
243
|
-
'marcel'
|
244
|
-
:content_type => 'text/plain')
|
252
|
+
'marcel')
|
245
253
|
|
246
254
|
# Streamed upload
|
247
255
|
S3Object.store('roots.mpeg',
|
248
256
|
File.open('roots.mpeg'),
|
249
|
-
'marcel'
|
250
|
-
:content_type => 'audio/mpeg')
|
257
|
+
'marcel')
|
251
258
|
|
252
259
|
|
253
260
|
== Setting the current bucket
|
@@ -265,8 +272,7 @@ For all methods that take a bucket name as an argument, the current bucket will
|
|
265
272
|
other_song = '/Users/marcel/baby-please-come-home.mp3'
|
266
273
|
JukeBoxSong.store(
|
267
274
|
File.basename(other_song),
|
268
|
-
File.open(other_song)
|
269
|
-
:content_type => 'audio/mpeg'
|
275
|
+
File.open(other_song)
|
270
276
|
)
|
271
277
|
|
272
278
|
This time we didn't have to explicitly pass in the bucket name, as the JukeBoxSong class knows that it will
|
@@ -327,7 +333,7 @@ You can set a canned access level when you create a bucket or an object by using
|
|
327
333
|
'kiss.jpg',
|
328
334
|
data,
|
329
335
|
'marcel',
|
330
|
-
:
|
336
|
+
:access => :public_read
|
331
337
|
)
|
332
338
|
|
333
339
|
Since the image we created is publicly readable, we can access it directly from a browser by going to the corresponding bucket name
|
data/Rakefile
CHANGED
data/lib/aws/s3.rb
CHANGED
@@ -10,6 +10,7 @@ require 'date'
|
|
10
10
|
$:.unshift(File.dirname(__FILE__))
|
11
11
|
require 's3/extensions'
|
12
12
|
require_library_or_gem 'builder' unless defined? Builder
|
13
|
+
require_library_or_gem 'mime/types' unless defined? MIME::Types
|
13
14
|
|
14
15
|
require 's3/base'
|
15
16
|
require 's3/version'
|
@@ -42,12 +43,8 @@ AWS::S3::S3Object.class_eval do
|
|
42
43
|
end
|
43
44
|
|
44
45
|
require_library_or_gem 'xmlsimple' unless defined? XmlSimple
|
45
|
-
#
|
46
|
-
# it
|
47
|
-
# and consumes way too much memory (beach balls a MacBookPro with 2GB of memory for 2 minutes while parsing 60KB of xml).
|
48
|
-
#
|
49
|
-
# So, if libxml is installed, we use the FasterXmlSimple library, that provides most of the functionality of XmlSimple
|
50
|
-
# except it uses the xml/libxml library for xml parsing. If libxml isn't installed, we just fall back on
|
46
|
+
# If libxml is installed, we use the FasterXmlSimple library, that provides most of the functionality of XmlSimple
|
47
|
+
# except it uses the xml/libxml library for xml parsing (rather than REXML). If libxml isn't installed, we just fall back on
|
51
48
|
# XmlSimple.
|
52
49
|
AWS::S3::Parsing.parser =
|
53
50
|
begin
|
data/lib/aws/s3/acl.rb
CHANGED
@@ -16,7 +16,7 @@ module AWS
|
|
16
16
|
# 'kiss.jpg',
|
17
17
|
# data,
|
18
18
|
# 'marcel',
|
19
|
-
# :
|
19
|
+
# :access => :public_read
|
20
20
|
# )
|
21
21
|
#
|
22
22
|
# Since the image we created is publicly readable, we can access it directly from a browser by going to the corresponding bucket name
|
data/lib/aws/s3/base.rb
CHANGED
@@ -114,8 +114,7 @@ module AWS #:nodoc:
|
|
114
114
|
# other_song = '/Users/marcel/baby-please-come-home.mp3'
|
115
115
|
# JukeBoxSong.store(
|
116
116
|
# File.basename(other_song),
|
117
|
-
# File.open(other_song)
|
118
|
-
# :content_type => 'audio/mpeg'
|
117
|
+
# File.open(other_song)
|
119
118
|
# )
|
120
119
|
#
|
121
120
|
# This time we didn't have to explicitly pass in the bucket name, as the JukeBoxSong class knows that it will
|
data/lib/aws/s3/bucket.rb
CHANGED
@@ -38,12 +38,9 @@ module AWS
|
|
38
38
|
# S3Object.store(
|
39
39
|
# file,
|
40
40
|
# File.open(file),
|
41
|
-
# 'jukebox'
|
42
|
-
# :content_type => 'audio/mpeg'
|
41
|
+
# 'jukebox'
|
43
42
|
# )
|
44
|
-
#
|
45
|
-
# Though strictly not required, you should specify the content type of the file so that when you go to download it your browser will know how to handle the file.
|
46
|
-
#
|
43
|
+
#
|
47
44
|
# You'll see your file has been added to it:
|
48
45
|
#
|
49
46
|
# music_bucket.objects
|
data/lib/aws/s3/object.rb
CHANGED
@@ -8,8 +8,20 @@ module AWS
|
|
8
8
|
# S3Object.store(
|
9
9
|
# 'headshot.jpg',
|
10
10
|
# File.open('headshot.jpg'),
|
11
|
-
# 'photos'
|
12
|
-
#
|
11
|
+
# 'photos'
|
12
|
+
# )
|
13
|
+
#
|
14
|
+
# The content type of the object will be infered by its extension. If the appropriate content type can not be infered, S3 defaults
|
15
|
+
# to <tt>binary/octect-stream</tt>.
|
16
|
+
#
|
17
|
+
# If you want to override this, you can explicitly indicate what content type the object should have with the <tt>:content_type</tt> option:
|
18
|
+
#
|
19
|
+
# file = 'black-flowers.m4a'
|
20
|
+
# S3Object.store(
|
21
|
+
# file,
|
22
|
+
# File.open(file),
|
23
|
+
# 'jukebox',
|
24
|
+
# :content_type => 'audio/mp4a-latm'
|
13
25
|
# )
|
14
26
|
#
|
15
27
|
# You can read more about storing files on S3 in the documentation for S3Object.store.
|
@@ -61,7 +73,7 @@ module AWS
|
|
61
73
|
#
|
62
74
|
# You can change the content type as well if you like:
|
63
75
|
#
|
64
|
-
# song.content_type = 'application/
|
76
|
+
# song.content_type = 'application/pdf'
|
65
77
|
# song.store
|
66
78
|
#
|
67
79
|
# (Keep in mind that due to limitiations in S3's exposed API, the only way to change things like the content_type
|
@@ -197,17 +209,19 @@ module AWS
|
|
197
209
|
# # Non streamed upload
|
198
210
|
# S3Object.store('simple-text-file.txt',
|
199
211
|
# 'hello world!',
|
200
|
-
# 'marcel'
|
201
|
-
# :content_type => 'text/plain')
|
212
|
+
# 'marcel')
|
202
213
|
#
|
203
214
|
# # Streamed upload
|
204
215
|
# S3Object.store('roots.mpeg',
|
205
216
|
# File.open('roots.mpeg'),
|
206
|
-
# 'marcel'
|
207
|
-
# :content_type => 'audio/mpeg')
|
217
|
+
# 'marcel')
|
208
218
|
def store(key, data, bucket = nil, options = {})
|
209
219
|
validate_key!(key)
|
210
|
-
|
220
|
+
# Must build path before infering content type in case bucket is being used for options
|
221
|
+
path = path!(bucket, key, options)
|
222
|
+
infer_content_type!(key, options)
|
223
|
+
|
224
|
+
put(path, options, data) # Don't call .success? on response. We want to get the etag.
|
211
225
|
end
|
212
226
|
alias_method :create, :store
|
213
227
|
alias_method :save, :store
|
@@ -259,12 +273,19 @@ module AWS
|
|
259
273
|
end
|
260
274
|
'/' << File.join(bucket_name(bucket), name)
|
261
275
|
end
|
262
|
-
|
276
|
+
|
263
277
|
private
|
264
278
|
|
265
279
|
def validate_key!(key)
|
266
280
|
raise InvalidKeyName.new(key) unless key && key.size <= 1024
|
267
281
|
end
|
282
|
+
|
283
|
+
def infer_content_type!(key, options)
|
284
|
+
return if options.has_key?(:content_type)
|
285
|
+
if mime_type = MIME::Types.type_for(key).first
|
286
|
+
options[:content_type] = mime_type.content_type
|
287
|
+
end
|
288
|
+
end
|
268
289
|
end
|
269
290
|
|
270
291
|
class Value < String #:nodoc:
|
data/lib/aws/s3/version.rb
CHANGED
@@ -2,9 +2,9 @@ module AWS
|
|
2
2
|
module S3
|
3
3
|
module VERSION #:nodoc:
|
4
4
|
MAJOR = '0'
|
5
|
-
MINOR = '
|
6
|
-
TINY = '
|
7
|
-
BETA =
|
5
|
+
MINOR = '2'
|
6
|
+
TINY = '0'
|
7
|
+
BETA = nil # Time.now.to_i.to_s
|
8
8
|
end
|
9
9
|
|
10
10
|
Version = [VERSION::MAJOR, VERSION::MINOR, VERSION::TINY, VERSION::BETA].compact * '.'
|
data/test/object_test.rb
CHANGED
@@ -40,6 +40,22 @@ class ObjectTest < Test::Unit::TestCase
|
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
43
|
+
def test_content_type_inference
|
44
|
+
[
|
45
|
+
['foo.jpg', {}, 'image/jpeg'],
|
46
|
+
['foo.txt', {}, 'text/plain'],
|
47
|
+
['foo', {}, nil],
|
48
|
+
['foo.asdf', {}, nil],
|
49
|
+
['foo.jpg', {:content_type => nil}, nil],
|
50
|
+
['foo', {:content_type => 'image/jpg'}, 'image/jpg'],
|
51
|
+
['foo.jpg', {:content_type => 'image/png'}, 'image/png'],
|
52
|
+
['foo.asdf', {:content_type => 'image/jpg'}, 'image/jpg']
|
53
|
+
].each do |key, options, content_type|
|
54
|
+
S3Object.send(:infer_content_type!, key, options)
|
55
|
+
assert_equal content_type, options[:content_type]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
43
59
|
def test_object_has_owner
|
44
60
|
assert_kind_of Owner, @object.owner
|
45
61
|
end
|
data/test/remote/object_test.rb
CHANGED
@@ -264,4 +264,31 @@ class RemoteS3ObjectTest < Test::Unit::TestCase
|
|
264
264
|
object.delete
|
265
265
|
end
|
266
266
|
end
|
267
|
+
|
268
|
+
def test_content_type_inference
|
269
|
+
# Confirm appropriate content type is infered when not specified
|
270
|
+
|
271
|
+
content_type_objects = {'foo.jpg' => 'image/jpeg', 'no-extension-specified' => 'binary/octet-stream', 'foo.txt' => 'text/plain'}
|
272
|
+
content_type_objects.each_key do |key|
|
273
|
+
S3Object.store(key, 'fake data', TEST_BUCKET) # No content type explicitly set
|
274
|
+
end
|
275
|
+
|
276
|
+
content_type_objects.each do |key, content_type|
|
277
|
+
assert_equal content_type, S3Object.about(key, TEST_BUCKET)['content-type']
|
278
|
+
end
|
279
|
+
|
280
|
+
# Confirm we can update the content type
|
281
|
+
|
282
|
+
assert_nothing_raised do
|
283
|
+
object = S3Object.find('no-extension-specified', TEST_BUCKET)
|
284
|
+
object.content_type = 'application/pdf'
|
285
|
+
object.store
|
286
|
+
end
|
287
|
+
|
288
|
+
assert_equal 'application/pdf', S3Object.about('no-extension-specified', TEST_BUCKET)['content-type']
|
289
|
+
|
290
|
+
ensure
|
291
|
+
# Get rid of objects we just created
|
292
|
+
content_type_objects.each_key {|key| S3Object.delete(key, TEST_BUCKET) }
|
293
|
+
end
|
267
294
|
end
|
metadata
CHANGED
@@ -3,7 +3,7 @@ rubygems_version: 0.9.0
|
|
3
3
|
specification_version: 1
|
4
4
|
name: aws-s3
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.
|
6
|
+
version: 0.2.0
|
7
7
|
date: 2006-11-30 00:00:00 -06:00
|
8
8
|
summary: Client library for Amazon's Simple Storage Service's REST API
|
9
9
|
require_paths:
|
@@ -123,3 +123,12 @@ dependencies:
|
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: 0.0.0
|
125
125
|
version:
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: mime-types
|
128
|
+
version_requirement:
|
129
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
130
|
+
requirements:
|
131
|
+
- - ">"
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: 0.0.0
|
134
|
+
version:
|