zip_tricks 4.2.2 → 4.2.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +38 -17
- data/lib/zip_tricks.rb +1 -1
- data/lib/zip_tricks/streamer/deflated_writer.rb +19 -3
- data/zip_tricks.gemspec +3 -3
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cc23010c353f0d1118cdbb38649c1363ffe34b7c
|
4
|
+
data.tar.gz: 8be7f24974d25870fd0b9c6852e0ad8fcff1ff0b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 15d547d8f049bd7eb71470632c43ccd836d24908d5e98061421caa0af28f8e1747bcbc993906e112fc2874af8b423d879510be2b6a49d1c346f820058f715e11
|
7
|
+
data.tar.gz: b16df9dcbb072b215f866f83cfd073157d21ca2d7e5f336e0226c509b858925e12149f831d816dbf159d041f0cfab27d16bb934692c66b7eefa5bdc048cbb5e1
|
data/README.md
CHANGED
@@ -3,17 +3,28 @@
|
|
3
3
|
[![Build Status](https://travis-ci.org/WeTransfer/zip_tricks.svg?branch=master)](https://travis-ci.org/WeTransfer/zip_tricks)
|
4
4
|
|
5
5
|
Allows streaming, non-rewinding ZIP file output from Ruby.
|
6
|
-
|
7
|
-
|
6
|
+
|
7
|
+
Initially written and as a spiritual successor to [zipline](https://github.com/fringd/zipline)
|
8
|
+
and now proudly powering it under the hood.
|
8
9
|
|
9
10
|
Allows you to write a ZIP archive out to a File, Socket, String or Array without having to rewind it at any
|
10
11
|
point. Usable for creating very large ZIP archives for immediate sending out to clients, or for writing
|
11
12
|
large ZIP archives without memory inflation.
|
12
13
|
|
13
|
-
|
14
|
+
zip_tricks currently handles all our zipping needs (millions of ZIP files generated per day), so we are
|
15
|
+
pretty confident it is widely compatible with a large number of unarchiving end-user applications.
|
16
|
+
|
17
|
+
## Requirements
|
18
|
+
|
19
|
+
Ruby 2.1+ syntax support (keyword arguments with defaults) and a working zlib (all available to jRuby as well).
|
20
|
+
jRuby might experience problems when using the reader methods due to the argument of `IO#seek` being limited
|
21
|
+
to [32 bit sizes.](https://github.com/jruby/jruby/issues/3817)
|
22
|
+
|
23
|
+
## Create a ZIP file without size estimation, compress on-the-fly during writes
|
14
24
|
|
15
|
-
|
16
|
-
|
25
|
+
Basic use case is compressing on the fly. Some data will be buffered by the Zlib deflater, but
|
26
|
+
memory inflation is going to be very constrained. Data will be written to destination at fairly regular
|
27
|
+
intervals. Deflate compression will work best for things like text files.
|
17
28
|
|
18
29
|
```ruby
|
19
30
|
out = my_tempfile # can also be a socket
|
@@ -26,8 +37,10 @@ ZipTricks::Streamer.open(out) do |zip|
|
|
26
37
|
end
|
27
38
|
end
|
28
39
|
```
|
40
|
+
Unfortunately with this approach it is impossible to compute the size of the ZIP file being output,
|
41
|
+
since you do not know how large the compressed data segments are going to be.
|
29
42
|
|
30
|
-
## Send
|
43
|
+
## Send a ZIP from a Rack response
|
31
44
|
|
32
45
|
Create a `RackBody` object and give it's constructor a block that adds files.
|
33
46
|
The block will only be called when actually sending the response to the client
|
@@ -50,6 +63,12 @@ end
|
|
50
63
|
Use the `SizeEstimator` to compute the correct size of the resulting archive.
|
51
64
|
|
52
65
|
```ruby
|
66
|
+
# Precompute the Content-Length ahead of time
|
67
|
+
bytesize = ZipTricks::SizeEstimator.estimate do |z|
|
68
|
+
z.add_stored_entry(filename: 'myfile1.bin', size: 9090821)
|
69
|
+
z.add_stored_entry(filename: 'myfile2.bin', size: 458678)
|
70
|
+
end
|
71
|
+
|
53
72
|
# Prepare the response body. The block will only be called when the response starts to be written.
|
54
73
|
zip_body = ZipTricks::RackBody.new do | zip |
|
55
74
|
zip.add_stored_entry(filename: "myfile1.bin", size: 9090821, crc32: 12485)
|
@@ -58,20 +77,9 @@ zip_body = ZipTricks::RackBody.new do | zip |
|
|
58
77
|
zip << read_file('myfile2.bin')
|
59
78
|
end
|
60
79
|
|
61
|
-
# Precompute the Content-Length ahead of time
|
62
|
-
bytesize = ZipTricks::SizeEstimator.estimate do |z|
|
63
|
-
z.add_stored_entry(filename: 'myfile1.bin', size: 9090821)
|
64
|
-
z.add_stored_entry(filename: 'myfile2.bin', size: 458678)
|
65
|
-
end
|
66
|
-
|
67
80
|
[200, {'Content-Length' => bytesize.to_s}, zip_body]
|
68
81
|
```
|
69
82
|
|
70
|
-
## Other usage examples
|
71
|
-
|
72
|
-
Check out the `examples/` directory at the root of the project. This will give you a good idea
|
73
|
-
of various use cases the library supports.
|
74
|
-
|
75
83
|
## Writing ZIP files using the Streamer bypass
|
76
84
|
|
77
85
|
You do not have to "feed" all the contents of the files you put in the archive through the Streamer object.
|
@@ -94,6 +102,11 @@ ZipTricks::Streamer.open(io) do | zip |
|
|
94
102
|
end
|
95
103
|
```
|
96
104
|
|
105
|
+
## Other usage examples
|
106
|
+
|
107
|
+
Check out the `examples/` directory at the root of the project. This will give you a good idea
|
108
|
+
of various use cases the library supports.
|
109
|
+
|
97
110
|
## Computing the CRC32 value of a large file
|
98
111
|
|
99
112
|
`BlockCRC32` computes the CRC32 checksum of an IO in a streaming fashion.
|
@@ -110,6 +123,13 @@ crc.to_i # Returns the actual CRC32 value computed so far
|
|
110
123
|
crc.append(precomputed_crc32, size_of_the_blob_computed_from)
|
111
124
|
```
|
112
125
|
|
126
|
+
## Reading ZIP files
|
127
|
+
|
128
|
+
The library contains a reader module, play with it to see what is possible. It is not a complete ZIP reader
|
129
|
+
but it was designed for a specific purpose (highly-parallel unpacking of remotely stored ZIP files), and
|
130
|
+
as such it performs it's function quite well. Please beware of the security implications of using ZIP readers
|
131
|
+
that have not been formally verified (ours hasn't been).
|
132
|
+
|
113
133
|
## Contributing to zip_tricks
|
114
134
|
|
115
135
|
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
|
@@ -119,6 +139,7 @@ crc.append(precomputed_crc32, size_of_the_blob_computed_from)
|
|
119
139
|
* Commit and push until you are happy with your contribution.
|
120
140
|
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
121
141
|
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
142
|
+
* If you alter the `ZipWriter`, please take the time to run the test in the `testing/` directory and verify the generated files do open. You will need fast storage to run those tests.
|
122
143
|
|
123
144
|
## Copyright
|
124
145
|
|
data/lib/zip_tricks.rb
CHANGED
@@ -1,21 +1,29 @@
|
|
1
1
|
class ZipTricks::Streamer::DeflatedWriter
|
2
|
+
# After how many bytes of incoming data the deflater for the
|
3
|
+
# contents must be flushed. This is done to prevent unreasonable
|
4
|
+
# memory use when archiving large files.
|
5
|
+
FLUSH_EVERY_N_BYTES = 1024 * 1024 * 5
|
6
|
+
|
2
7
|
def initialize(io)
|
3
8
|
@io = io
|
4
9
|
@uncompressed_size = 0
|
5
10
|
@started_at = @io.tell
|
6
11
|
@crc = ZipTricks::StreamCRC32.new
|
12
|
+
@deflater = ::Zlib::Deflate.new(Zlib::DEFAULT_COMPRESSION, -::Zlib::MAX_WBITS)
|
7
13
|
@bytes_since_last_flush = 0
|
8
14
|
end
|
9
15
|
|
10
16
|
def finish
|
11
|
-
|
17
|
+
@io << @deflater.finish until @deflater.finished?
|
12
18
|
[@crc.to_i, @io.tell - @started_at, @uncompressed_size]
|
13
19
|
end
|
14
20
|
|
15
21
|
def <<(data)
|
16
22
|
@uncompressed_size += data.bytesize
|
17
|
-
@
|
23
|
+
@bytes_since_last_flush += data.bytesize
|
24
|
+
@io << @deflater.deflate(data)
|
18
25
|
@crc << data
|
26
|
+
interim_flush
|
19
27
|
self
|
20
28
|
end
|
21
29
|
|
@@ -23,4 +31,12 @@ class ZipTricks::Streamer::DeflatedWriter
|
|
23
31
|
self << data
|
24
32
|
data.bytesize
|
25
33
|
end
|
26
|
-
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def interim_flush
|
38
|
+
return if @bytes_since_last_flush < FLUSH_EVERY_N_BYTES
|
39
|
+
@io << @deflater.flush
|
40
|
+
@bytes_since_last_flush = 0
|
41
|
+
end
|
42
|
+
end
|
data/zip_tricks.gemspec
CHANGED
@@ -2,16 +2,16 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
-
# stub: zip_tricks 4.2.
|
5
|
+
# stub: zip_tricks 4.2.3 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "zip_tricks"
|
9
|
-
s.version = "4.2.
|
9
|
+
s.version = "4.2.3"
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
12
12
|
s.require_paths = ["lib"]
|
13
13
|
s.authors = ["Julik Tarkhanov"]
|
14
|
-
s.date = "2016-11-
|
14
|
+
s.date = "2016-11-18"
|
15
15
|
s.description = "Stream out ZIP files from Ruby"
|
16
16
|
s.email = "me@julik.nl"
|
17
17
|
s.extra_rdoc_files = [
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: zip_tricks
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.2.
|
4
|
+
version: 4.2.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Julik Tarkhanov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-11-
|
11
|
+
date: 2016-11-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rubyzip
|