aws 2.5.8 → 2.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (2) hide show
  1. data/lib/s3/s3_interface.rb +168 -2
  2. metadata +2 -2
@@ -113,6 +113,14 @@ module Aws
113
113
  out_string << '?torrent' if path[/[&?]torrent($|&|=)/]
114
114
  out_string << '?location' if path[/[&?]location($|&|=)/]
115
115
  out_string << '?logging' if path[/[&?]logging($|&|=)/] # this one is beta, no support for now
116
+ #... also deal with params for multipart uploads API
117
+ out_string << '?uploads' if path[/\?uploads$/]
118
+ if path[/\?uploadId=(.*)$/]
119
+ out_string << "?uploadId=#{$1}"
120
+ end
121
+ if path[/\?partNumber=(\d*)&uploadId=(.*)$/]
122
+ out_string << "?partNumber=#{$1}&uploadId=#{$2}"
123
+ end
116
124
  out_string
117
125
  end
118
126
 
@@ -338,7 +346,7 @@ module Aws
338
346
  begin
339
347
  internal_bucket = bucket.dup
340
348
  unless internal_options.nil? || internal_options.empty?
341
- internal_bucket << '?'
349
+ internal_bucket << '?'
342
350
  internal_bucket << internal_options.map { |k, v| "#{k.to_s}=#{CGI::escape v.to_s}" }.join('&')
343
351
  end
344
352
  req_hash = generate_rest_request('GET', headers.merge(:url=>internal_bucket))
@@ -518,6 +526,112 @@ module Aws
518
526
  r[:verified_md5] ? (return r) : (raise AwsError.new("Uploaded object failed MD5 checksum verification: #{r.inspect}"))
519
527
  end
520
528
 
529
+ # Initiates a multipart upload and returns an upload ID or an exception
530
+ # http://docs.amazonwebservices.com/AmazonS3/latest/API/mpUploadInitiate.html
531
+ #
532
+ # s3.initiate_multipart('my_awesome_bucket', 'hugeObject') => WL7dk8sqbtk3Rg641HHWaNeG6RxI4fzS8V0YvuQAfs5Hbk6WNZOU1z_AhGv
533
+ #
534
+ # The returned uploadId must be retained for use in uploading parts; see
535
+ # http://docs.amazonwebservices.com/AmazonS3/latest/dev/mpuoverview.html
536
+ #
537
+ def initiate_multipart(bucket, key, headers={})
538
+ req_hash = generate_rest_request('POST', headers.merge(:url =>"#{bucket}/#{CGI::escape key}?uploads"))
539
+ request_info(req_hash, S3InitiateMultipartUploadParser.new)
540
+ rescue
541
+ on_exception
542
+ end
543
+
544
+ # Uploads a part in a multipart upload - returns an Etag for the part or an exception
545
+ # http://docs.amazonwebservices.com/AmazonS3/latest/API/mpUploadUploadPart.html
546
+ #
547
+ # Among the parameters required, clients must supply the uploadId (obtained from the initiate_multipart method call) as
548
+ # well as the partNumber for this part (user-specified, determining the sequence for reassembly).
549
+ #
550
+ # s3.upload_part('my_awesome_bucket', 'hugeObject', "WL7dk8sqbtk3Rg641HHWaNeG6RxI", "2", File.open('localfilename.dat'))
551
+ # => "b54357faf0632cce46e942fa68356b38"
552
+ #
553
+ # The return Etag must be retained for use in the completion of the multipart upload; see
554
+ # http://docs.amazonwebservices.com/AmazonS3/latest/dev/mpuoverview.html
555
+ #
556
+ def upload_part(bucket, key, uploadId, partNumber, data, headers={})
557
+ if (data.respond_to?(:binmode))
558
+ data.binmode
559
+ end
560
+ if data.is_a?(String)
561
+ data = StringIO.new(data)
562
+ end
563
+ data_size = data.respond_to?(:lstat) ? data.lstat.size :
564
+ (data.respond_to?(:size) ? data.size : 0)
565
+ if (data_size >= USE_100_CONTINUE_PUT_SIZE)
566
+ headers['expect'] = '100-continue'
567
+ end
568
+ req_hash = generate_rest_request('PUT', headers.merge(:url =>"#{bucket}/#{CGI::escape key}?partNumber=#{partNumber}&uploadId=#{uploadId}",
569
+ :data => data,
570
+ 'Content-Length' => data_size.to_s))
571
+ request_info(req_hash, S3UploadPartParser.new)
572
+ rescue
573
+ on_exception
574
+ end
575
+
576
+
577
+ # Completes a multipart upload, returning true or an exception
578
+ # http://docs.amazonwebservices.com/AmazonS3/latest/API/mpUploadComplete.html
579
+ #
580
+ # Clients must specify the uploadId (obtained from the initiate_multipart call) and the reassembly manifest hash
581
+ # which specifies the each partNumber corresponding etag (obtained from the upload_part call):
582
+ #
583
+ # s3.complete_multipart('my_awesome_bucket', 'hugeObject', "WL7dk8sqbtk3Rg641HHWaNeG6RxI",
584
+ # {"1"=>"a54357aff0632cce46d942af68356b38", "2"=>"0c78aef83f66abc1fa1e8477f296d394"}) => true
585
+ #
586
+ # See http://docs.amazonwebservices.com/AmazonS3/latest/dev/mpuoverview.html
587
+ #
588
+ def complete_multipart(bucket, key, uploadId, manifest_hash, headers={})
589
+ parts_string = manifest_hash.inject("") do |res, (part,etag)|
590
+ res<< <<END_PARTS
591
+ <Part>
592
+ <PartNumber>#{part}</PartNumber>
593
+ <ETag>"#{etag}"</ETag>
594
+ </Part>
595
+ END_PARTS
596
+ res
597
+ end
598
+ data = <<EOS
599
+ <CompleteMultipartUpload>
600
+ #{parts_string}
601
+ </CompleteMultipartUpload>
602
+ EOS
603
+ req_hash = generate_rest_request('POST', headers.merge(:url => "#{bucket}/#{CGI::escape key}?uploadId=#{uploadId}",
604
+ :data => data))
605
+ request_info(req_hash, RightHttp2xxParser.new)
606
+ rescue
607
+ on_exception
608
+ end
609
+
610
+ # List parts of a multipart upload, returning a hash or an exception
611
+ # http://docs.amazonwebservices.com/AmazonS3/latest/API/mpUploadListParts.html
612
+ #
613
+ # response looks like:
614
+ #
615
+ # { :bucket=>"mariosFoo_awesome_test_bucket_000A1",
616
+ # :key=>"mariosFoosegmented",
617
+ # :upload_id=>"jQKX7JdJBTrbvLn9apUPIXkt14FHdp6nMZVg--"
618
+ # :parts=> [ {:part_number=>"1", :last_modified=>"2012-10-30T15:06:28.000Z",
619
+ # :etag=>"\"78f871f6f01673a4aca05b1f8e26df08\"", :size=>"6276589"},
620
+ # {:part_number=>"2", :last_modified=>"2012-10-30T15:08:22.000Z",
621
+ # :etag=>"\"e7b94a1e959ca066026da3ec63aad321\"", :size=>"7454095"}] }
622
+ #
623
+ # Clients must specify the uploadId (obtained from the initiate_multipart call)
624
+ #
625
+ # s3.list_parts('my_awesome_bucket', 'hugeObject', "WL7dk8sqbtk3Rg641HHWaNeG6RxI",
626
+ #
627
+ # See http://docs.amazonwebservices.com/AmazonS3/latest/dev/mpuoverview.html
628
+ #
629
+ def list_parts(bucket, key, uploadId, headers={})
630
+ req_hash = generate_rest_request('GET', headers.merge(:url=>"#{bucket}/#{CGI::escape key}?uploadId=#{uploadId}"))
631
+ request_info(req_hash, S3ListMultipartPartsParser.new)
632
+ end
633
+
634
+
521
635
  # Retrieves object data from Amazon. Returns a +hash+ or an exception.
522
636
  #
523
637
  # s3.get('my_awesome_bucket', 'log/curent/1.log') #=>
@@ -544,7 +658,6 @@ module Aws
544
658
  # end
545
659
  # foo.close
546
660
  #
547
-
548
661
  def get(bucket, key, headers={}, &block)
549
662
  req_hash = generate_rest_request('GET', headers.merge(:url=>"#{bucket}/#{CGI::escape key}"))
550
663
  request_info(req_hash, S3HttpResponseBodyParser.new, &block)
@@ -1235,6 +1348,53 @@ module Aws
1235
1348
  end
1236
1349
  end
1237
1350
 
1351
+ class S3InitiateMultipartUploadParser < AwsParser # :nodoc:
1352
+ def reset
1353
+ @result = ""
1354
+ end
1355
+
1356
+ def tagend(name)
1357
+ @result = @text if name == 'UploadId'
1358
+ end
1359
+
1360
+ end
1361
+
1362
+ class S3ListMultipartPartsParser < AwsParser # :nodoc:
1363
+ def reset
1364
+ @result = {}
1365
+ @result[:parts] = []
1366
+ @current_part={}
1367
+ end
1368
+
1369
+ def tagstart(name, attributes)
1370
+ @current_part={} if name=='Part'
1371
+ end
1372
+
1373
+ def tagend(name)
1374
+ case name
1375
+ when 'PartNumber'
1376
+ @current_part[:part_number] = @text
1377
+ when 'ETag'
1378
+ @current_part[:etag] = @text
1379
+ when 'Size'
1380
+ @current_part[:size] = @text
1381
+ when 'LastModified'
1382
+ @current_part[:last_modified] = @text
1383
+ when 'Bucket'
1384
+ @result[:bucket] = @text
1385
+ when 'Key'
1386
+ @result[:key] = @text
1387
+ when 'UploadId'
1388
+ @result[:upload_id] = @text
1389
+ when 'Part'
1390
+ @result[:parts] << @current_part
1391
+ end
1392
+ end
1393
+
1394
+ end
1395
+
1396
+
1397
+
1238
1398
  #-----------------------------------------------------------------
1239
1399
  # PARSERS: Non XML
1240
1400
  #-----------------------------------------------------------------
@@ -1274,6 +1434,12 @@ module Aws
1274
1434
  end
1275
1435
  end
1276
1436
 
1437
+ class S3UploadPartParser < S3HttpResponseParser # :nodoc:
1438
+ def parse(response)
1439
+ @result = headers_to_string(response.to_hash)["etag"].gsub!("\"", "")
1440
+ end
1441
+ end
1442
+
1277
1443
  end
1278
1444
 
1279
1445
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aws
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.5.8
4
+ version: 2.6.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2012-10-04 00:00:00.000000000 Z
14
+ date: 2012-11-28 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: uuidtools