zip_kit 6.2.2 → 6.3.0
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.
- 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.
|