aws-s3 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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
- :content_type => 'image/jpg'
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/octet-stream'
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
- :content_type => 'image/jpg', :access => :public_read
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
@@ -74,6 +74,7 @@ namespace :dist do
74
74
 
75
75
  s.add_dependency 'xml-simple'
76
76
  s.add_dependency 'builder'
77
+ s.add_dependency 'mime-types'
77
78
  s.rdoc_options = ['--title', "AWS::S3 -- Support for Amazon S3's REST api",
78
79
  '--main', 'README',
79
80
  '--line-numbers', '--inline-source']
@@ -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
- # XmlSimple is a very convenient way of dealing with the xml needs of this library, but unfortunately
46
- # it is powered by REXML which is both very slow (even for me who does not privilege performance)
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
@@ -16,7 +16,7 @@ module AWS
16
16
  # 'kiss.jpg',
17
17
  # data,
18
18
  # 'marcel',
19
- # :content_type => 'image/jpg', :access => :public_read
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
@@ -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
@@ -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
@@ -8,8 +8,20 @@ module AWS
8
8
  # S3Object.store(
9
9
  # 'headshot.jpg',
10
10
  # File.open('headshot.jpg'),
11
- # 'photos',
12
- # :content_type => 'image/jpg'
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/octet-stream'
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
- put(path!(bucket, key, options), options, data) # Don't call .success? on response. We want to get the etag.
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:
@@ -2,9 +2,9 @@ module AWS
2
2
  module S3
3
3
  module VERSION #:nodoc:
4
4
  MAJOR = '0'
5
- MINOR = '1'
6
- TINY = '2'
7
- BETA = nil # Time.now.to_i.to_s
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 * '.'
@@ -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
@@ -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.1.2
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: