zipline 0.0.10 → 0.0.11

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.
@@ -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