Process everything in chunks

The old implementation loaded files into memory to provide an IO interface. This has the obvious downside of loading any file included in the import, e.g. a 10GB video file, into memory. ZipKit has no native IO object for reading but it provides all the necessary methods to implement one.
This commit is contained in:
Stanko K.R.
2026-01-30 16:48:33 +01:00
parent dd13a3b87c
commit 5bbd7f633d
3 changed files with 28 additions and 10 deletions
+2 -3
View File
@@ -10,12 +10,11 @@ class ZipFile::Reader
raise ArgumentError, "Cannot read directory entry: #{file_path}" if entry.filename.end_with?("/")
extractor = entry.extractor_from(@io)
content = extractor.extract
if block_given?
yield StringIO.new(content)
yield ZipFile::Reader::ExtractorIO.new(extractor)
else
content
extractor.extract
end
end
@@ -0,0 +1,23 @@
class ZipFile::Reader::ExtractorIO
def initialize(extractor)
@extractor = extractor
end
def read(length = nil, buffer = nil)
return nil if @extractor.eof?
data = @extractor.extract(length)
return nil if data.nil?
if buffer
buffer.replace(data)
buffer
else
data
end
end
def eof?
@extractor.eof?
end
end
+3 -7
View File
@@ -26,16 +26,12 @@ class ZipFile::Writer
def add_file(path, content = nil, compress: true)
@entries << path
compression = compress ? :deflate : :stored
write_method = compress ? :write_deflated_file : :write_stored_file
if block_given?
streamer.write_deflated_file(path) do |sink|
yield sink
end
streamer.public_send(write_method, path) { |sink| yield sink }
else
streamer.write_deflated_file(path) do |sink|
sink.write(content)
end
streamer.public_send(write_method, path) { |sink| sink.write(content) }
end
end