zip_kit 6.2.2 → 6.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.yardopts +1 -1
- data/CHANGELOG.md +4 -0
- data/CONTRIBUTING.md +1 -1
- data/IMPLEMENTATION_DETAILS.md +2 -2
- data/README.md +11 -6
- data/RUBYZIP_DIFFERENCES.md +56 -0
- data/Rakefile +1 -5
- data/lib/zip_kit/rails_streaming.rb +2 -3
- data/lib/zip_kit/railtie.rb +7 -0
- data/lib/zip_kit/version.rb +1 -1
- data/lib/zip_kit.rb +2 -0
- data/rbi/zip_kit.rbi +6 -4
- data/zip_kit.gemspec +2 -1
- metadata +21 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dcd59b7f9d367a40895c9bac2f909f3e22ebd0a96ee737073ef5153c4d486c70
|
4
|
+
data.tar.gz: 05665ca021d401cad02f80c38d8965c2e5fef1a477317f7ee92246d1c54a21ae
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b13d15a467565ef66ce6a21ac3891e8a26b30246d538c232aca193c3fe24a24a8f3a2d844d48eaeaeeb5ccc2f92cfcaab20e4afa1a2717b89ba27f55bb4635e4
|
7
|
+
data.tar.gz: 29aacf905b670323861812a4aece1446917ac2f94ece22b948f5d2f77a6eb7574c39598177e7c4f33cc230fd863b4f1c02eb961c5b48e4823d40854a25368101
|
data/.yardopts
CHANGED
@@ -1 +1 @@
|
|
1
|
-
--markup markdown
|
1
|
+
--markup markdown --no-private --protected lib/**/*.rb - LICENSE.txt IMPLEMENTATION_DETAILS.md RUBYZIP_DIFFERENCES.md CONTRIBUTING.md CODE_OF_CONDUCT.md CHANGELOG.md
|
data/CHANGELOG.md
CHANGED
data/CONTRIBUTING.md
CHANGED
@@ -16,7 +16,7 @@ If you are interested in contributing code and would like to learn more about th
|
|
16
16
|
|
17
17
|
- [ruby](https://ruby-doc.org)
|
18
18
|
- [rubyzip](https://github.com/rubyzip/rubyzip) as we like to test "our implementation against theirs"
|
19
|
-
- [rspec](http://rspec.info/)
|
19
|
+
- [rspec](http://rspec.info/) for testing
|
20
20
|
- [zip files](https://en.wikipedia.org/wiki/Zip_(file_format))
|
21
21
|
|
22
22
|
# How do I make a contribution?
|
data/IMPLEMENTATION_DETAILS.md
CHANGED
@@ -78,8 +78,8 @@ you can try this:
|
|
78
78
|
|
79
79
|
[Encoding::CP437, Encoding::ISO_8859_1, Encoding::UTF_8]
|
80
80
|
|
81
|
-
|
82
|
-
|
81
|
+
While this could work, we found it to be broken in practice as the decoding of the filename
|
82
|
+
also depends on the system locale.
|
83
83
|
|
84
84
|
Additionally, the tests with the unarchivers we _do_ support have shown that including the InfoZIP
|
85
85
|
extra field does not actually help any of them recognize the file name correctly. And the use of
|
data/README.md
CHANGED
@@ -14,8 +14,13 @@ point. Usable for creating very large ZIP archives for immediate sending out to
|
|
14
14
|
large ZIP archives without memory inflation.
|
15
15
|
|
16
16
|
The original gem (zip_tricks) handled all the zipping needs (millions of ZIP files generated per day),
|
17
|
-
for
|
18
|
-
|
17
|
+
for WeTransfer, it is widely compatible with a large number of unarchiving end-user applications.
|
18
|
+
|
19
|
+
## How does it work? How is it different from Rubyzip?
|
20
|
+
|
21
|
+
Check out [the implementation details](IMPLEMENTATION_DETAILS.md) on the design of the library, and
|
22
|
+
we have a separate [reference](RUBYZIP_DIFFERENCES.md) on why you might want to use ZipKit over
|
23
|
+
Rubyzip and vice versa.
|
19
24
|
|
20
25
|
## Requirements
|
21
26
|
|
@@ -23,13 +28,11 @@ Ruby 2.6+ syntax support is required, as well as a a working zlib (all available
|
|
23
28
|
|
24
29
|
## Diving in: send some large CSV reports from Rails
|
25
30
|
|
26
|
-
The
|
27
|
-
|
31
|
+
The included `Railtie` will automatically include `ZipKit::RailsStreaming` into the
|
32
|
+
`ActionController::Base` class. You will then have a `zip_kit_stream` method available which accepts a block:
|
28
33
|
|
29
34
|
```ruby
|
30
35
|
class ZipsController < ActionController::Base
|
31
|
-
include ZipKit::RailsStreaming
|
32
|
-
|
33
36
|
def download
|
34
37
|
zip_kit_stream do |zip|
|
35
38
|
zip.write_file('report1.csv') do |sink|
|
@@ -48,6 +51,8 @@ class ZipsController < ActionController::Base
|
|
48
51
|
end
|
49
52
|
```
|
50
53
|
|
54
|
+
The block receives the `ZipKit::Streamer` object you can write your files through.
|
55
|
+
|
51
56
|
The `write_file` method will use some heuristics to determine whether your output file would benefit
|
52
57
|
from compression, and pick the appropriate storage mode for the file accordingly.
|
53
58
|
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# Key differences between Rubyzip and ZipKit
|
2
|
+
|
3
|
+
Please bear in mind that this is written down not to disparage [Rubyzip.](https://github.com/rubyzip/rubyzip)
|
4
|
+
|
5
|
+
Rubyzip is, by all means, a very mature, fully featured library, and while ZipKit does have overlap with it in some functionality there are
|
6
|
+
differences in supported features which may be important for you when choosing.
|
7
|
+
|
8
|
+
## What ZipKit supports and Rubyzip does not
|
9
|
+
|
10
|
+
* ZipKit outputs archives in a streaming fashion, using data descriptors.
|
11
|
+
This allows output of archives of very large size, without buffering.
|
12
|
+
Rubyzip will seek in the already written archive to overwrite the local entry after the write of every file into the output ZIP.
|
13
|
+
At the moment, it is difficult to build a streaming Rubyzip solution due to the output of extra field placeholders.
|
14
|
+
* ZipKit supports block-deflate which allows for distributed compression of files
|
15
|
+
* ZipKit reads files from the central directory, which allows for very rapid reading. Reading works well with data descriptors
|
16
|
+
and Zip64, and is economical enough to enable "remote uncapping" where pieces of a ZIP file get read over HTTP to reconstruct
|
17
|
+
the archive structure. Actual reading can then be done on a per-entry basis. Rubyzip reads entry data from local entries, which
|
18
|
+
is error prone and much less economical than using the central directory
|
19
|
+
* ZipKit deliberately _does not_ allow you to crawl directories to add to an archive, as this has been used for security exploits
|
20
|
+
in Rubyzip.
|
21
|
+
* ZipKit deliberately _does not_ allow you to extract a ZIP archive directly to the filesystem, as this has been used for security
|
22
|
+
exploits in Rubyzip.
|
23
|
+
* When writing, ZipKit applies careful buffering to speed up CRC32 calculations. Rubyzip combines CRC32 values at every write, which
|
24
|
+
can be slow if there are many small writes.
|
25
|
+
* ZipKit comes with a Rails helper and a Rack-compatible response body for facilitating streaming. Rubyzip has no Rails integration
|
26
|
+
and no Rack integration.
|
27
|
+
* ZipKit allows you to estimate the exact size of an archive ahead of time
|
28
|
+
* ZipKit has a heuristic module which picks the storage mode (stored or deflated) depending on how well your input compresses
|
29
|
+
* ZipKit requires components using autoloading, which means that your application will likely boot faster as you will almost never
|
30
|
+
need all of the features in one codebase. Rubyzip requires its components eagerly.
|
31
|
+
* ZipKit comes with exhaustive YARD documentation and `.rbi` typedefs for [Sorbet/Tapioca](https://sorbet.org/blog/2022/07/27/srb-tapioca)
|
32
|
+
|
33
|
+
## What Rubyzip supports and ZipKit does not
|
34
|
+
|
35
|
+
* Rubyzip allows limited manipulation of existing ZIP files by overwriting the archive entries
|
36
|
+
* Rubyzip supports "classic" ZIP encryption - both for reading and writing. ZipKit has no encryption support.
|
37
|
+
* Rubyzip allows extraction into a directory, ZipKit avoids implementing this for security reasons
|
38
|
+
* Rubyzip allows archiving a directory, ZipKit avoids implementing this for security reasons
|
39
|
+
* Rubyzip supports separate atime and ctime in the `UniversalTime` extra fields. ZipKit outputs just one timestamp
|
40
|
+
* Rubyzip attempts to faithfully replicate UNIX permissions on the files being output. ZipKit does not attempt that
|
41
|
+
because it turned out that these permissions can break unarchiving of folders on macOS.
|
42
|
+
|
43
|
+
## Where there is currently feature parity
|
44
|
+
|
45
|
+
These used to be different, but Rubyzip has made great progress in addressing.
|
46
|
+
|
47
|
+
* ZipKit automatically applies the EFS flag for Unicode filenames in the archive. This used to be optional in RubyZip
|
48
|
+
* ZipKit automatically enables Zip64 and does so only when necessary. applies the EFS flag for Unicode filenames in the archive. This used to be optional in RubyZip.
|
49
|
+
* ZipKit outputs the `UT` precise time extra field
|
50
|
+
* ZipKit used to be distributed under the MIT-Hippocratic license which is much more restrictive than the Rubyzip BSD-2-Clause. ZipKit is now MIT-licensed.
|
51
|
+
|
52
|
+
## Code style differences
|
53
|
+
|
54
|
+
Rubyzip is written in a somewhat Java-like style, with a lot of encapsulation and data hiding. ZipKit aims to be more approachable and have "less" of everything.
|
55
|
+
Less modules, less classes, less OOP - just enough to be useful. But that is a matter of taste, and as such should not matter to you all that much
|
56
|
+
when picking one over the other. Or it might, you never know ;-)
|
data/Rakefile
CHANGED
@@ -11,11 +11,7 @@ task :format do
|
|
11
11
|
`bundle exec magic_frozen_string_literal ./lib`
|
12
12
|
end
|
13
13
|
|
14
|
-
YARD::Rake::YardocTask.new(:doc)
|
15
|
-
# The dash has to be between the two to "divide" the source files and
|
16
|
-
# miscellaneous documentation files that contain no code
|
17
|
-
t.files = ["lib/**/*.rb", "-", "LICENSE.txt", "IMPLEMENTATION_DETAILS.md"]
|
18
|
-
end
|
14
|
+
YARD::Rake::YardocTask.new(:doc)
|
19
15
|
RSpec::Core::RakeTask.new(:spec)
|
20
16
|
|
21
17
|
task :generate_typedefs do
|
@@ -3,8 +3,7 @@
|
|
3
3
|
# Should be included into a Rails controller for easy ZIP output from any action.
|
4
4
|
module ZipKit::RailsStreaming
|
5
5
|
# Opens a {ZipKit::Streamer} and yields it to the caller. The output of the streamer
|
6
|
-
#
|
7
|
-
# the Rails response stream is going to be closed automatically.
|
6
|
+
# will be sent through to the HTTP response body as it gets produced.
|
8
7
|
#
|
9
8
|
# Note that there is an important difference in how this method works, depending whether
|
10
9
|
# you use it in a controller which includes `ActionController::Live` vs. one that does not.
|
@@ -25,7 +24,7 @@ module ZipKit::RailsStreaming
|
|
25
24
|
# @param use_chunked_transfer_encoding[Boolean] whether to forcibly encode output as chunked. Normally you should not need this.
|
26
25
|
# @param output_enumerator_options[Hash] options that will be passed to the OutputEnumerator - these include
|
27
26
|
# options for the Streamer. See {ZipKit::OutputEnumerator#initialize} for the full list of options.
|
28
|
-
# @yieldparam [ZipKit::Streamer] the
|
27
|
+
# @yieldparam [ZipKit::Streamer] zip the {ZipKit::Streamer} that can be written to
|
29
28
|
# @return [Boolean] always returns true
|
30
29
|
def zip_kit_stream(filename: "download.zip", type: "application/zip", use_chunked_transfer_encoding: false, **output_enumerator_options, &zip_streaming_blk)
|
31
30
|
# We want some common headers for file sending. Rails will also set
|
data/lib/zip_kit/version.rb
CHANGED
data/lib/zip_kit.rb
CHANGED
@@ -24,4 +24,6 @@ module ZipKit
|
|
24
24
|
autoload :WriteShovel, File.dirname(__FILE__) + "/zip_kit/write_shovel.rb"
|
25
25
|
autoload :RackChunkedBody, File.dirname(__FILE__) + "/zip_kit/rack_chunked_body.rb"
|
26
26
|
autoload :RackTempfileBody, File.dirname(__FILE__) + "/zip_kit/rack_tempfile_body.rb"
|
27
|
+
|
28
|
+
require_relative "zip_kit/railtie" if defined?(::Rails)
|
27
29
|
end
|
data/rbi/zip_kit.rbi
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
# typed: strong
|
2
2
|
module ZipKit
|
3
|
-
VERSION = T.let("6.
|
3
|
+
VERSION = T.let("6.3.0", T.untyped)
|
4
|
+
|
5
|
+
class Railtie < Rails::Railtie
|
6
|
+
end
|
4
7
|
|
5
8
|
# A ZIP archive contains a flat list of entries. These entries can implicitly
|
6
9
|
# create directories when the archive is expanded. For example, an entry with
|
@@ -1976,8 +1979,7 @@ end, T.untyped)
|
|
1976
1979
|
# Should be included into a Rails controller for easy ZIP output from any action.
|
1977
1980
|
module RailsStreaming
|
1978
1981
|
# Opens a {ZipKit::Streamer} and yields it to the caller. The output of the streamer
|
1979
|
-
#
|
1980
|
-
# the Rails response stream is going to be closed automatically.
|
1982
|
+
# will be sent through to the HTTP response body as it gets produced.
|
1981
1983
|
#
|
1982
1984
|
# Note that there is an important difference in how this method works, depending whether
|
1983
1985
|
# you use it in a controller which includes `ActionController::Live` vs. one that does not.
|
@@ -2008,7 +2010,7 @@ end, T.untyped)
|
|
2008
2010
|
type: String,
|
2009
2011
|
use_chunked_transfer_encoding: T::Boolean,
|
2010
2012
|
output_enumerator_options: T::Hash[T.untyped, T.untyped],
|
2011
|
-
zip_streaming_blk: T.proc.params(
|
2013
|
+
zip_streaming_blk: T.proc.params(zip: ZipKit::Streamer).void
|
2012
2014
|
).returns(T::Boolean)
|
2013
2015
|
end
|
2014
2016
|
def zip_kit_stream(filename: "download.zip", type: "application/zip", use_chunked_transfer_encoding: false, **output_enumerator_options, &zip_streaming_blk); end
|
data/zip_kit.gemspec
CHANGED
@@ -27,7 +27,7 @@ Gem::Specification.new do |spec|
|
|
27
27
|
# zip_kit does not use any runtime dependencies (besides zlib). However, for testing
|
28
28
|
# things quite a few things are used - and for a good reason.
|
29
29
|
|
30
|
-
spec.add_development_dependency "rubyzip", "~>
|
30
|
+
spec.add_development_dependency "rubyzip", "~> 2" # We test our output with _another_ ZIP library, which is the way to go here
|
31
31
|
spec.add_development_dependency "rack" # For tests where we spin up a server. Both for streaming out and for testing reads over HTTP
|
32
32
|
spec.add_development_dependency "rake", "~> 12.2"
|
33
33
|
spec.add_development_dependency "rspec", "~> 3"
|
@@ -40,6 +40,7 @@ Gem::Specification.new do |spec|
|
|
40
40
|
spec.add_development_dependency "standard", "1.28.5" # Very specific version of standard for 2.6 with _known_ settings
|
41
41
|
spec.add_development_dependency "magic_frozen_string_literal"
|
42
42
|
spec.add_development_dependency "puma"
|
43
|
+
spec.add_development_dependency "rails", "~> 5" # For testing RailsStreaming against an actual Rails controller
|
43
44
|
spec.add_development_dependency "actionpack", "~> 5" # For testing RailsStreaming against an actual Rails controller
|
44
45
|
spec.add_development_dependency "nokogiri", "~> 1", ">= 1.13" # Rails 5 does by mistake use an older Nokogiri otherwise
|
45
46
|
spec.add_development_dependency "sinatra"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: zip_kit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 6.
|
4
|
+
version: 6.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Julik Tarkhanov
|
@@ -12,7 +12,7 @@ authors:
|
|
12
12
|
autorequire:
|
13
13
|
bindir: exe
|
14
14
|
cert_chain: []
|
15
|
-
date: 2024-
|
15
|
+
date: 2024-04-01 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: bundler
|
@@ -34,14 +34,14 @@ dependencies:
|
|
34
34
|
requirements:
|
35
35
|
- - "~>"
|
36
36
|
- !ruby/object:Gem::Version
|
37
|
-
version: '
|
37
|
+
version: '2'
|
38
38
|
type: :development
|
39
39
|
prerelease: false
|
40
40
|
version_requirements: !ruby/object:Gem::Requirement
|
41
41
|
requirements:
|
42
42
|
- - "~>"
|
43
43
|
- !ruby/object:Gem::Version
|
44
|
-
version: '
|
44
|
+
version: '2'
|
45
45
|
- !ruby/object:Gem::Dependency
|
46
46
|
name: rack
|
47
47
|
requirement: !ruby/object:Gem::Requirement
|
@@ -216,6 +216,20 @@ dependencies:
|
|
216
216
|
- - ">="
|
217
217
|
- !ruby/object:Gem::Version
|
218
218
|
version: '0'
|
219
|
+
- !ruby/object:Gem::Dependency
|
220
|
+
name: rails
|
221
|
+
requirement: !ruby/object:Gem::Requirement
|
222
|
+
requirements:
|
223
|
+
- - "~>"
|
224
|
+
- !ruby/object:Gem::Version
|
225
|
+
version: '5'
|
226
|
+
type: :development
|
227
|
+
prerelease: false
|
228
|
+
version_requirements: !ruby/object:Gem::Requirement
|
229
|
+
requirements:
|
230
|
+
- - "~>"
|
231
|
+
- !ruby/object:Gem::Version
|
232
|
+
version: '5'
|
219
233
|
- !ruby/object:Gem::Dependency
|
220
234
|
name: actionpack
|
221
235
|
requirement: !ruby/object:Gem::Requirement
|
@@ -298,6 +312,7 @@ files:
|
|
298
312
|
- IMPLEMENTATION_DETAILS.md
|
299
313
|
- LICENSE.txt
|
300
314
|
- README.md
|
315
|
+
- RUBYZIP_DIFFERENCES.md
|
301
316
|
- Rakefile
|
302
317
|
- bench/buffered_crc32_bench.rb
|
303
318
|
- examples/archive_size_estimate.rb
|
@@ -319,6 +334,7 @@ files:
|
|
319
334
|
- lib/zip_kit/rack_chunked_body.rb
|
320
335
|
- lib/zip_kit/rack_tempfile_body.rb
|
321
336
|
- lib/zip_kit/rails_streaming.rb
|
337
|
+
- lib/zip_kit/railtie.rb
|
322
338
|
- lib/zip_kit/remote_io.rb
|
323
339
|
- lib/zip_kit/remote_uncap.rb
|
324
340
|
- lib/zip_kit/size_estimator.rb
|
@@ -358,7 +374,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
358
374
|
- !ruby/object:Gem::Version
|
359
375
|
version: '0'
|
360
376
|
requirements: []
|
361
|
-
rubygems_version: 3.
|
377
|
+
rubygems_version: 3.0.3
|
362
378
|
signing_key:
|
363
379
|
specification_version: 4
|
364
380
|
summary: Stream out ZIP files from Ruby. Successor to zip_tricks.
|