s3_streamer 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 158368a84fcdfe9ac40904f3a922b4da9b4ccae2
4
- data.tar.gz: 4d659a39ebde78e65b0b878a0def086789a43299
3
+ metadata.gz: 08b8b13f35734bff5cbdcb9a4cf1ba0770b0671d
4
+ data.tar.gz: 570918eb21651ecd7a1bd3545395c1eccd1691db
5
5
  SHA512:
6
- metadata.gz: 5bcec56c4f9cd00f6873c086fd8b12f5a6e59b511b927b20de747129ebab426c644b8002e23a39634213bb007ac0b28a2d370652be242696c40775738749b58a
7
- data.tar.gz: ff0fb774181964ac67cefc507c32c9ba4213751d5267674cfdd53d5eb270b9aaca26a6b5fc790594a6720f61867b5a468f42f1333b468c12ebedc67dca779836
6
+ metadata.gz: 8a7cfe74390bd782a5f5b7af9e440b8260dc7a8c215d1e1a9fcb573ecc42ea466a1d4ff35976181b4f7e8b3bcbb11238f62754c811ad0fb74bb43e6a6e317083
7
+ data.tar.gz: 6bc5a341149f6d92ddce682fd5904f9a19260bdb901a166390a28d8d7f79995914d87c8af27f1c30726269750b1bd1361fbf595cbf7b7210eac3958f4e724d81
data/README.md CHANGED
@@ -1,3 +1,5 @@
1
+ [![Build Status](https://travis-ci.org/thilonel/s3_streamer.svg?branch=master)](https://travis-ci.org/thilonel/s3_streamer)
2
+
1
3
  # S3 Streamer
2
4
 
3
5
  Stream a file from a remote url using the Ruby AWS SDK to an Amazon S3 bucket.
@@ -0,0 +1,35 @@
1
+ module S3Streamer
2
+ class BufferedWriter
3
+ attr_reader :options, :buffer
4
+
5
+ def initialize(options, &block)
6
+ @options = options
7
+ @block = block
8
+ clear
9
+ end
10
+
11
+ def push(chunk)
12
+ @buffer << chunk
13
+ write if @buffer.size > min_part_size
14
+ end
15
+
16
+ def finish
17
+ write if @buffer.size > 0
18
+ end
19
+
20
+ private
21
+
22
+ def write
23
+ @block.call buffer
24
+ clear
25
+ end
26
+
27
+ def min_part_size
28
+ options[:min_part_size] || 1024
29
+ end
30
+
31
+ def clear
32
+ @buffer = ""
33
+ end
34
+ end
35
+ end
@@ -1,18 +1,20 @@
1
1
  require 'aws-sdk'
2
2
 
3
- require 's3_streamer/client/downstream'
4
- require 's3_streamer/client/upstream'
3
+ require 's3_streamer/downstream'
4
+ require 's3_streamer/upstream'
5
5
 
6
6
  module S3Streamer
7
7
  class Client
8
+ attr_reader :client
9
+
8
10
  def initialize(options)
9
11
  @client = Aws::S3::Client.new(options)
10
12
  end
11
13
 
12
- def stream(source_uri, bucket, destination_file)
13
- upstream = Upstream.new @client, bucket, destination_file
14
+ def stream(source_uri, bucket, destination_file, options={})
15
+ upstream = Upstream.new client, bucket, destination_file
14
16
 
15
- Downstream.new(URI(source_uri)).each do |chunk|
17
+ Downstream.new(URI(source_uri), options).each do |chunk|
16
18
  upstream.upload chunk
17
19
  end
18
20
 
@@ -0,0 +1,33 @@
1
+ require 'net/http'
2
+ require 's3_streamer/buffered_writer'
3
+
4
+ module S3Streamer
5
+ class Downstream
6
+ DEFAULT_PART_SIZE = 10 * 1024 * 1024
7
+
8
+ def initialize(uri, options={})
9
+ @uri = uri
10
+ @options = options
11
+ end
12
+
13
+ def each
14
+ Net::HTTP.start(@uri.host) do |http|
15
+ http.request(Net::HTTP::Get.new @uri) do |response|
16
+ buffer = BufferedWriter.new(min_part_size: part_size) do |part|
17
+ yield part
18
+ end
19
+
20
+ response.read_body { |chunk| buffer.push chunk }
21
+
22
+ buffer.finish
23
+ end
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ def part_size
30
+ @options[:part_size] || DEFAULT_PART_SIZE
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,37 @@
1
+ module S3Streamer
2
+ class Upstream
3
+ def initialize(client, bucket, destination_file)
4
+ @client = client
5
+ @bucket = bucket
6
+ @destination_file = destination_file
7
+ @parts = []
8
+ @part_number = 1
9
+ @upload_id = create
10
+ end
11
+
12
+ def upload(chunk)
13
+ uploaded_part = @client.upload_part(body: chunk,
14
+ bucket: @bucket,
15
+ key: @destination_file,
16
+ part_number: @part_number,
17
+ upload_id: @upload_id)
18
+
19
+ @parts << {etag: uploaded_part.etag, part_number: @part_number}
20
+
21
+ @part_number += 1
22
+ end
23
+
24
+ def complete
25
+ @client.complete_multipart_upload(bucket: @bucket,
26
+ key: @destination_file,
27
+ upload_id: @upload_id,
28
+ multipart_upload: {parts: @parts})
29
+ end
30
+
31
+ private
32
+
33
+ def create
34
+ @client.create_multipart_upload(bucket: @bucket, key: @destination_file).upload_id
35
+ end
36
+ end
37
+ end
@@ -1,3 +1,3 @@
1
1
  module S3Streamer
2
- VERSION = '0.1.1'
2
+ VERSION = '0.2.0'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: s3_streamer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - thilonel
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-06-02 00:00:00.000000000 Z
11
+ date: 2016-07-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -99,10 +99,10 @@ files:
99
99
  - bin/console
100
100
  - bin/setup
101
101
  - lib/s3_streamer.rb
102
+ - lib/s3_streamer/buffered_writer.rb
102
103
  - lib/s3_streamer/client.rb
103
- - lib/s3_streamer/client/downstream.rb
104
- - lib/s3_streamer/client/downstream/chunk_buffer.rb
105
- - lib/s3_streamer/client/upstream.rb
104
+ - lib/s3_streamer/downstream.rb
105
+ - lib/s3_streamer/upstream.rb
106
106
  - lib/s3_streamer/version.rb
107
107
  - s3_streamer.gemspec
108
108
  homepage: https://github.com/thilonel/s3_streamer
@@ -1,18 +0,0 @@
1
- class ChunkBuffer
2
- def initialize(response, chunks_per_buffer = 10240)
3
- @response = response
4
- @chunks_per_buffer = chunks_per_buffer
5
- end
6
-
7
- def each
8
- buffer = []
9
- @response.read_body do |chunk|
10
- buffer << chunk
11
- if buffer.size >= @chunks_per_buffer
12
- yield buffer.join
13
- buffer = []
14
- end
15
- end
16
- yield buffer.join if buffer.size > 0
17
- end
18
- end
@@ -1,18 +0,0 @@
1
- require 'net/http'
2
- require_relative 'downstream/chunk_buffer'
3
-
4
- class Downstream
5
- def initialize(uri)
6
- @uri = uri
7
- end
8
-
9
- def each
10
- Net::HTTP.start(@uri.host) do |http|
11
- http.request(Net::HTTP::Get.new @uri) do |response|
12
- ChunkBuffer.new(response).each do |chunk|
13
- yield chunk
14
- end
15
- end
16
- end
17
- end
18
- end
@@ -1,35 +0,0 @@
1
- class Upstream
2
- def initialize(client, bucket, destination_file)
3
- @client = client
4
- @bucket = bucket
5
- @destination_file = destination_file
6
- @parts = []
7
- @part_number = 1
8
- @upload_id = create
9
- end
10
-
11
- def upload(chunk)
12
- uploaded_part = @client.upload_part(body: chunk,
13
- bucket: @bucket,
14
- key: @destination_file,
15
- part_number: @part_number,
16
- upload_id: @upload_id)
17
-
18
- @parts << {etag: uploaded_part.etag, part_number: @part_number}
19
-
20
- @part_number += 1
21
- end
22
-
23
- def complete
24
- @client.complete_multipart_upload(bucket: @bucket,
25
- key: @destination_file,
26
- upload_id: @upload_id,
27
- multipart_upload: {parts: @parts})
28
- end
29
-
30
- private
31
-
32
- def create
33
- @client.create_multipart_upload(bucket: @bucket, key: @destination_file).upload_id
34
- end
35
- end