s3_multi_upload 0.0.1
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/bin/s3_multi_upload +26 -0
- data/lib/s3_multi_upload.rb +87 -0
- metadata +82 -0
data/bin/s3_multi_upload
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
$:.unshift File.join File.dirname(__FILE__), *%w[.. lib]
|
|
3
|
+
%w[thor s3_multi_upload].each {|l| require l}
|
|
4
|
+
|
|
5
|
+
module S3_Multi_Upload
|
|
6
|
+
class Task < Thor
|
|
7
|
+
|
|
8
|
+
desc 'upload', 'upload a file to s3 in parallel'
|
|
9
|
+
method_option :access_key_id, :required => true
|
|
10
|
+
method_option :secret_access_key, :required => true
|
|
11
|
+
method_option :bucket, :required => true
|
|
12
|
+
method_option :file, :required => true
|
|
13
|
+
method_option :threads, :required => true, :type => :numeric, :default => 5
|
|
14
|
+
method_option :chunk_size, :required => true, :type => :hash, :default => {10 => :mb}
|
|
15
|
+
method_option :progress_bar, :type => :boolean, :default => true
|
|
16
|
+
method_option :key, :desc => 's3 object key (default: file name)'
|
|
17
|
+
|
|
18
|
+
def upload
|
|
19
|
+
Upload.new(options).process
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
default_task :upload
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
S3_Multi_Upload::Task.start
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
require 'pathname'
|
|
2
|
+
require 'aws-sdk'
|
|
3
|
+
require 'progressbar'
|
|
4
|
+
|
|
5
|
+
module S3_Multi_Upload
|
|
6
|
+
class Upload
|
|
7
|
+
attr_accessor :options, :file, :s3, :bucket, :object, :progress
|
|
8
|
+
|
|
9
|
+
def initialize options
|
|
10
|
+
|
|
11
|
+
AWS.config :access_key_id => options[:access_key_id],
|
|
12
|
+
:secret_access_key => options[:secret_access_key]
|
|
13
|
+
|
|
14
|
+
@options = options
|
|
15
|
+
@file = Pathname.new options[:file]
|
|
16
|
+
|
|
17
|
+
@s3 = AWS::S3.new
|
|
18
|
+
@bucket = @s3.buckets.create options[:bucket]
|
|
19
|
+
@object = @bucket.objects[options[:key] || @file.basename]
|
|
20
|
+
|
|
21
|
+
enqueue
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def normalize value, unit = nil
|
|
25
|
+
case unit.to_sym.downcase
|
|
26
|
+
when nil, :b, :byte, :bytes
|
|
27
|
+
value.to_f
|
|
28
|
+
when :k, :kb, :kilobyte, :kilobytes
|
|
29
|
+
value.to_f * 1024
|
|
30
|
+
when :m, :mb, :megabyte, :megabytes
|
|
31
|
+
value.to_f * 1024 ** 2
|
|
32
|
+
when :g, :gb, :gigabyte, :gigabytes
|
|
33
|
+
value.to_f * 1024 ** 3
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def chunk_size
|
|
38
|
+
normalize *options[:chunk_size].first
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def queue
|
|
42
|
+
@queue ||= Queue.new
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def enqueue
|
|
46
|
+
(file.size.to_f / chunk_size).ceil.times do |index|
|
|
47
|
+
queue << [chunk_size * index, index + 1]
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def upload
|
|
52
|
+
object.multipart_upload do |upload|
|
|
53
|
+
threads = []
|
|
54
|
+
|
|
55
|
+
options[:threads].times do
|
|
56
|
+
threads << Thread.new do
|
|
57
|
+
until queue.empty?
|
|
58
|
+
offset, index = queue.deq :asynchronously rescue nil
|
|
59
|
+
|
|
60
|
+
unless offset.nil?
|
|
61
|
+
upload.add_part :data => file.read(chunk_size, offset),
|
|
62
|
+
:part_number => index
|
|
63
|
+
|
|
64
|
+
progress.inc if options[:progress_bar]
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
threads.each &:join
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def progress
|
|
75
|
+
@progress ||= ProgressBar.new :upload, queue.size
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def process
|
|
79
|
+
value, unit = *options[:chunk_size].first
|
|
80
|
+
puts "uploading #{file} to s3://#{options[:bucket]}/#{object.key} using #{options[:threads]} threads in chunks of #{value} #{unit}"
|
|
81
|
+
progress if options[:progress_bar]
|
|
82
|
+
abort 'upload failed' unless upload
|
|
83
|
+
progress.finish if options[:progress_bar]
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
end
|
|
87
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: s3_multi_upload
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.1
|
|
5
|
+
prerelease:
|
|
6
|
+
platform: ruby
|
|
7
|
+
authors:
|
|
8
|
+
- dallas marlow
|
|
9
|
+
autorequire:
|
|
10
|
+
bindir: bin
|
|
11
|
+
cert_chain: []
|
|
12
|
+
date: 2012-04-23 00:00:00.000000000 Z
|
|
13
|
+
dependencies:
|
|
14
|
+
- !ruby/object:Gem::Dependency
|
|
15
|
+
name: aws-sdk
|
|
16
|
+
requirement: &70295147055820 !ruby/object:Gem::Requirement
|
|
17
|
+
none: false
|
|
18
|
+
requirements:
|
|
19
|
+
- - ! '>='
|
|
20
|
+
- !ruby/object:Gem::Version
|
|
21
|
+
version: '0'
|
|
22
|
+
type: :runtime
|
|
23
|
+
prerelease: false
|
|
24
|
+
version_requirements: *70295147055820
|
|
25
|
+
- !ruby/object:Gem::Dependency
|
|
26
|
+
name: thor
|
|
27
|
+
requirement: &70295147055280 !ruby/object:Gem::Requirement
|
|
28
|
+
none: false
|
|
29
|
+
requirements:
|
|
30
|
+
- - ! '>='
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '0'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: *70295147055280
|
|
36
|
+
- !ruby/object:Gem::Dependency
|
|
37
|
+
name: progressbar
|
|
38
|
+
requirement: &70295147054780 !ruby/object:Gem::Requirement
|
|
39
|
+
none: false
|
|
40
|
+
requirements:
|
|
41
|
+
- - ! '>='
|
|
42
|
+
- !ruby/object:Gem::Version
|
|
43
|
+
version: '0'
|
|
44
|
+
type: :runtime
|
|
45
|
+
prerelease: false
|
|
46
|
+
version_requirements: *70295147054780
|
|
47
|
+
description:
|
|
48
|
+
email:
|
|
49
|
+
- dallasmarlow@gmail.com
|
|
50
|
+
executables:
|
|
51
|
+
- s3_multi_upload
|
|
52
|
+
extensions: []
|
|
53
|
+
extra_rdoc_files: []
|
|
54
|
+
files:
|
|
55
|
+
- bin/s3_multi_upload
|
|
56
|
+
- lib/s3_multi_upload.rb
|
|
57
|
+
homepage: https://github.com/dallasmarlow/s3_multi_upload
|
|
58
|
+
licenses: []
|
|
59
|
+
post_install_message:
|
|
60
|
+
rdoc_options: []
|
|
61
|
+
require_paths:
|
|
62
|
+
- lib
|
|
63
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
64
|
+
none: false
|
|
65
|
+
requirements:
|
|
66
|
+
- - ! '>='
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '0'
|
|
69
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
70
|
+
none: false
|
|
71
|
+
requirements:
|
|
72
|
+
- - ! '>='
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: '0'
|
|
75
|
+
requirements: []
|
|
76
|
+
rubyforge_project:
|
|
77
|
+
rubygems_version: 1.8.10
|
|
78
|
+
signing_key:
|
|
79
|
+
specification_version: 3
|
|
80
|
+
summary: s3 multipart uploads in parallel
|
|
81
|
+
test_files: []
|
|
82
|
+
has_rdoc:
|