zipline 0.0.10 → 0.0.11

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f2f04b0aaf25dba39d30fa57d3b7dee52ab4f7db
4
+ data.tar.gz: af226cf8bd006c78e95e7fba5918b8888ab15893
5
+ SHA512:
6
+ metadata.gz: af1e5037946364838761db1c030dcb7c5480f779dc97a88117bcfc3f923097f598d1571ec87a27f83b1dc08c72e43b1176b5e379e5eca25f8f8cf9f30abd1eca
7
+ data.tar.gz: eb28c47cae2d33c2176242667d240747c632c71c210650645e35420d6af7ea5939319a14cefbc9b7e163c613b8e0acfebf524690c71f8ef6b795dbc4431f6d17
data/Gemfile CHANGED
@@ -4,7 +4,8 @@ source 'https://rubygems.org'
4
4
  gemspec
5
5
 
6
6
  group :development, :test do
7
- gem 'rspec', '~> 3.0.0.beta'
7
+ gem 'rubyzip', '~> 1.2'
8
+ gem 'rspec', '~> 3'
8
9
  gem 'fog'
9
10
  gem 'carrierwave'
10
11
  gem 'paperclip'
data/README.md CHANGED
@@ -17,10 +17,13 @@ And then execute:
17
17
 
18
18
  ## Usage
19
19
 
20
- set up some models with [carrierwave](https://github.com/jnicklas/carrierwave) or [paperclip](https://github.com/thoughtbot/paperclip).
21
- Right now only plain file storage and S3 are supported in the case of [carrierwave](https://github.com/jnicklas/carrierwave) and only plain file storage, not S3 in the case of [paperclip](https://github.com/thoughtbot/paperclip). Alternatively, you can pass in plain old File objects. Not to be judgy, but plain old file objects are probably not the best option most of the time.
22
-
23
- You'll need to be using [unicorn](http://unicorn.bogomips.org/) or rainbows or some other server that supports streaming output.
20
+ Set up some models with [carrierwave](https://github.com/jnicklas/carrierwave)
21
+ or [paperclip](https://github.com/thoughtbot/paperclip). Right now only plain
22
+ file storage and S3 are supported in the case of
23
+ [carrierwave](https://github.com/jnicklas/carrierwave) and only plain file
24
+ storage and S3 are supported in the case of
25
+ [paperclip](https://github.com/thoughtbot/paperclip).
26
+ You'll need to be using puma or some other server that supports streaming output.
24
27
 
25
28
  class MyController < ApplicationController
26
29
  # enable streaming responses
@@ -29,13 +32,29 @@ You'll need to be using [unicorn](http://unicorn.bogomips.org/) or rainbows or s
29
32
  include Zipline
30
33
 
31
34
  def index
32
- users= User.all
35
+ users = User.all
36
+ # you can replace user.avatar with any stream or any object that
37
+ # responds to :url
33
38
  files = users.map{ |user| [user.avatar, "#{user.username}.png"] }
34
39
  zipline( files, 'avatars.zip')
35
40
  end
36
41
  end
37
42
 
38
43
  For directories, just give the files names like "directory/file".
44
+
45
+ To stream files from a remote URL, use open-uri with a [lazy enumerator](http://ruby-doc.org/core-2.0.0/Enumerator/Lazy.html):
46
+
47
+ require 'open-uri'
48
+ avatars = [
49
+ # remote_url zip_path
50
+ [ 'http://www.example.com/user1.png', 'avatars/user1.png' ]
51
+ [ 'http://www.example.com/user2.png', 'avatars/user2.png' ]
52
+ [ 'http://www.example.com/user3.png', 'avatars/user3.png' ]
53
+ ]
54
+ file_mappings = avatars
55
+ .lazy # Lazy allows us to begin sending the download immediately instead of waiting to download everything
56
+ .map { |url, path| [open(url), path] }
57
+ zipline(file_mappings, 'avatars.zip')
39
58
 
40
59
  ## Contributing
41
60
 
@@ -48,5 +67,3 @@ For directories, just give the files names like "directory/file".
48
67
  ## TODO (possible contributions?)
49
68
 
50
69
  * tests!
51
- * extract library for plain ruby streaming zips, which this will depend on.
52
- * get my changes to support streaming zips checked in to the rubyzip library.
@@ -1,10 +1,6 @@
1
1
  require "zipline/version"
2
-
3
- require 'zip'
4
2
  require 'curb'
5
-
6
- require "zipline/fake_stream"
7
- require "zipline/output_stream"
3
+ require 'zip_tricks'
8
4
  require "zipline/zip_generator"
9
5
 
10
6
  # class MyController < ApplicationController
@@ -1,3 +1,3 @@
1
1
  module Zipline
2
- VERSION = "0.0.10"
2
+ VERSION = "0.0.11"
3
3
  end
@@ -13,21 +13,21 @@ module Zipline
13
13
  end
14
14
 
15
15
  def each(&block)
16
- output = new_output(&block)
17
- OutputStream.open(output) do |zip|
18
- @files.each {|file, name| handle_file(zip, file, name) }
16
+ fake_io_writer = ZipTricks::BlockWrite.new(&block)
17
+ ZipTricks::Streamer.open(fake_io_writer) do |streamer|
18
+ @files.each {|file, name| handle_file(streamer, file, name) }
19
19
  end
20
20
  end
21
21
 
22
- def handle_file(zip, file, name)
22
+ def handle_file(streamer, file, name)
23
23
  file = normalize(file)
24
24
  name = uniquify_name(name)
25
- write_file(zip, file, name)
25
+ write_file(streamer, file, name)
26
26
  end
27
27
 
28
28
  def normalize(file)
29
29
  unless is_io?(file)
30
- if file.respond_to?(:url) && (!defined?(::Paperclip::Attachment) || !file.is_a?(::Paperclip::Attachment))
30
+ if file.respond_to?(:url) || file.respond_to?(:expiring_url)
31
31
  file = file
32
32
  elsif file.respond_to? :file
33
33
  file = File.open(file.file)
@@ -40,42 +40,28 @@ module Zipline
40
40
  file
41
41
  end
42
42
 
43
- def new_output(&block)
44
- FakeStream.new(&block)
45
- end
46
-
47
- def write_file(zip, file, name)
48
- size = get_size(file)
49
- zip.put_next_entry name, size
50
-
51
- if is_io?(file)
52
- while buffer = file.read(2048)
53
- zip << buffer
54
- end
55
- else
56
- the_remote_url = file.url(Time.now + 1.minutes)
57
- c = Curl::Easy.new(the_remote_url) do |curl|
58
- curl.on_body do |data|
59
- zip << data
60
- data.bytesize
61
- end
43
+ def write_file(streamer, file, name)
44
+ streamer.write_stored_file(name) do |writer_for_file|
45
+ if file.respond_to?(:url) || file.respond_to?(:expiring_url)
46
+ # expiring_url seems needed for paperclip to work
47
+ the_remote_url = file.respond_to?(:expiring_url) ? file.expiring_url : file.url
48
+ c = Curl::Easy.new(the_remote_url) do |curl|
49
+ curl.on_body do |data|
50
+ writer_for_file << data
51
+ data.bytesize
52
+ end
53
+ end
54
+ c.perform
55
+ elsif is_io?(file)
56
+ IO.copy_stream(file, writer_for_file)
57
+ else
58
+ raise(ArgumentError, 'Bad File/Stream')
62
59
  end
63
- c.perform
64
- end
65
- end
66
-
67
- def get_size(file)
68
- if is_io?(file) || file.respond_to?(:size)
69
- file.size
70
- elsif file.respond_to? :content_length
71
- file.content_length
72
- else
73
- throw 'cannot determine file size'
74
60
  end
75
61
  end
76
62
 
77
- def is_io?(file)
78
- file.is_a?(IO) || (defined?(StringIO) && file.is_a?(StringIO))
63
+ def is_io?(io_ish)
64
+ io_ish.respond_to? :read
79
65
  end
80
66
 
81
67
  def uniquify_name(name)
@@ -8,7 +8,7 @@ Dir["#{File.expand_path('..', __FILE__)}/support/**/*.rb"].each { |f| require f
8
8
 
9
9
 
10
10
  RSpec.configure do |config|
11
- config.color_enabled = true
11
+ config.color = true
12
12
  config.order = :random
13
13
  config.run_all_when_everything_filtered = true
14
14
  end
@@ -4,7 +4,7 @@ require File.expand_path('../lib/zipline/version', __FILE__)
4
4
  Gem::Specification.new do |gem|
5
5
  gem.authors = ["Ram Dobson"]
6
6
  gem.email = ["ram.dobson@solsystemscompany.com"]
7
- gem.description = %q{this is a giant pile of hax that may let you stream dynamically generated zip files}
7
+ gem.description = %q{a module for streaming dynamically generated zip files}
8
8
  gem.summary = %q{stream zip files from rails}
9
9
  gem.homepage = "http://github.com/fringd/zipline"
10
10
 
@@ -15,7 +15,7 @@ Gem::Specification.new do |gem|
15
15
  gem.require_paths = ["lib"]
16
16
  gem.version = Zipline::VERSION
17
17
 
18
- gem.add_dependency 'rubyzip', ['>= 1.0', '<= 1.1.2']
19
- gem.add_dependency 'rails', ['>= 3.2.1', '< 4.3']
20
- gem.add_dependency 'curb'
18
+ gem.add_dependency 'zip_tricks', ['>= 4.0.0', '<= 5.0.0']
19
+ gem.add_dependency 'rails', ['>= 3.2.1', '< 5.1']
20
+ gem.add_dependency 'curb', ['>= 0.8.0', '< 0.10']
21
21
  end
metadata CHANGED
@@ -1,78 +1,76 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zipline
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.10
5
- prerelease:
4
+ version: 0.0.11
6
5
  platform: ruby
7
6
  authors:
8
7
  - Ram Dobson
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2015-05-26 00:00:00.000000000 Z
11
+ date: 2016-09-06 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
- name: rubyzip
14
+ name: zip_tricks
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ! '>='
17
+ - - ">="
20
18
  - !ruby/object:Gem::Version
21
- version: '1.0'
22
- - - <=
19
+ version: 4.0.0
20
+ - - "<="
23
21
  - !ruby/object:Gem::Version
24
- version: 1.1.2
22
+ version: 5.0.0
25
23
  type: :runtime
26
24
  prerelease: false
27
25
  version_requirements: !ruby/object:Gem::Requirement
28
- none: false
29
26
  requirements:
30
- - - ! '>='
27
+ - - ">="
31
28
  - !ruby/object:Gem::Version
32
- version: '1.0'
33
- - - <=
29
+ version: 4.0.0
30
+ - - "<="
34
31
  - !ruby/object:Gem::Version
35
- version: 1.1.2
32
+ version: 5.0.0
36
33
  - !ruby/object:Gem::Dependency
37
34
  name: rails
38
35
  requirement: !ruby/object:Gem::Requirement
39
- none: false
40
36
  requirements:
41
- - - ! '>='
37
+ - - ">="
42
38
  - !ruby/object:Gem::Version
43
39
  version: 3.2.1
44
- - - <
40
+ - - "<"
45
41
  - !ruby/object:Gem::Version
46
- version: '4.3'
42
+ version: '5.1'
47
43
  type: :runtime
48
44
  prerelease: false
49
45
  version_requirements: !ruby/object:Gem::Requirement
50
- none: false
51
46
  requirements:
52
- - - ! '>='
47
+ - - ">="
53
48
  - !ruby/object:Gem::Version
54
49
  version: 3.2.1
55
- - - <
50
+ - - "<"
56
51
  - !ruby/object:Gem::Version
57
- version: '4.3'
52
+ version: '5.1'
58
53
  - !ruby/object:Gem::Dependency
59
54
  name: curb
60
55
  requirement: !ruby/object:Gem::Requirement
61
- none: false
62
56
  requirements:
63
- - - ! '>='
57
+ - - ">="
64
58
  - !ruby/object:Gem::Version
65
- version: '0'
59
+ version: 0.8.0
60
+ - - "<"
61
+ - !ruby/object:Gem::Version
62
+ version: '0.10'
66
63
  type: :runtime
67
64
  prerelease: false
68
65
  version_requirements: !ruby/object:Gem::Requirement
69
- none: false
70
66
  requirements:
71
- - - ! '>='
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: 0.8.0
70
+ - - "<"
72
71
  - !ruby/object:Gem::Version
73
- version: '0'
74
- description: this is a giant pile of hax that may let you stream dynamically generated
75
- zip files
72
+ version: '0.10'
73
+ description: a module for streaming dynamically generated zip files
76
74
  email:
77
75
  - ram.dobson@solsystemscompany.com
78
76
  executables: []
@@ -84,8 +82,6 @@ files:
84
82
  - README.md
85
83
  - Rakefile
86
84
  - lib/zipline.rb
87
- - lib/zipline/fake_stream.rb
88
- - lib/zipline/output_stream.rb
89
85
  - lib/zipline/version.rb
90
86
  - lib/zipline/zip_generator.rb
91
87
  - spec/lib/zipline/zip_generator_spec.rb
@@ -93,27 +89,26 @@ files:
93
89
  - zipline.gemspec
94
90
  homepage: http://github.com/fringd/zipline
95
91
  licenses: []
92
+ metadata: {}
96
93
  post_install_message:
97
94
  rdoc_options: []
98
95
  require_paths:
99
96
  - lib
100
97
  required_ruby_version: !ruby/object:Gem::Requirement
101
- none: false
102
98
  requirements:
103
- - - ! '>='
99
+ - - ">="
104
100
  - !ruby/object:Gem::Version
105
101
  version: '0'
106
102
  required_rubygems_version: !ruby/object:Gem::Requirement
107
- none: false
108
103
  requirements:
109
- - - ! '>='
104
+ - - ">="
110
105
  - !ruby/object:Gem::Version
111
106
  version: '0'
112
107
  requirements: []
113
108
  rubyforge_project:
114
- rubygems_version: 1.8.23
109
+ rubygems_version: 2.5.1
115
110
  signing_key:
116
- specification_version: 3
111
+ specification_version: 4
117
112
  summary: stream zip files from rails
118
113
  test_files:
119
114
  - spec/lib/zipline/zip_generator_spec.rb
@@ -1,43 +0,0 @@
1
- #this is a class that acts like an IO::Stream, but really puts to the browser
2
- module Zipline
3
- class FakeStream
4
-
5
- # &block is the block that each gets from rails... we pass it strings to send data
6
- def initialize(&block)
7
- @block = block
8
- @pos = 0
9
- end
10
-
11
- def tell
12
- @pos
13
- end
14
-
15
- def pos
16
- @pos
17
- end
18
-
19
- def seek
20
- throw :fit
21
- end
22
-
23
- def pos=
24
- throw :fit
25
- end
26
-
27
- def to_s
28
- throw :fit
29
- end
30
-
31
- def <<(x)
32
- return if x.blank?
33
- throw "bad class #{x.class}" unless x.class == String
34
- @pos += x.bytesize
35
- @block.call(x.to_s)
36
- end
37
-
38
- def close
39
- nil
40
- end
41
-
42
- end
43
- end
@@ -1,55 +0,0 @@
1
- # a ZipOutputStream that never rewinds output
2
- # in order for that to be possible we store only uncompressed files
3
- module Zipline
4
- class OutputStream < Zip::OutputStream
5
-
6
- #we need to be able to hand out own custom output in order to stream to browser
7
- def initialize(io)
8
- # Create an io stream thing
9
- super StringIO.new, true
10
- # Overwrite it with my own
11
- @output_stream = io
12
- end
13
-
14
- def stream
15
- @output_stream
16
- end
17
-
18
- def put_next_entry(entry_name, size)
19
- new_entry = Zip::Entry.new(@file_name, entry_name)
20
-
21
- #THIS IS THE MAGIC, tells zip to look after data for size, crc
22
- new_entry.gp_flags = new_entry.gp_flags | 0x0008
23
-
24
- super(new_entry)
25
-
26
- # Uncompressed size in the local file header must be zero when bit 3
27
- # of the general purpose flags is set, so set the size after the header
28
- # has been written.
29
- new_entry.size = size
30
- end
31
-
32
- # just reset state, no rewinding required
33
- def finalize_current_entry
34
- if current_entry
35
- entry = current_entry
36
- super
37
- write_local_footer(entry)
38
- end
39
- end
40
-
41
- def write_local_footer(entry)
42
- @output_stream << [ 0x08074b50, entry.crc, entry.compressed_size, entry.size].pack('VVVV')
43
- end
44
-
45
- #never need to do this because we set correct sizes up front
46
- def update_local_headers
47
- nil
48
- end
49
-
50
- # helper to deal with difference between rubyzip 1.0 and 1.1
51
- def current_entry
52
- @currentEntry || @current_entry
53
- end
54
- end
55
- end