zip_tricks 将不会收到进一步的更新或支持,并且将不再进行维护。 zip_tricks 的故事在 zip_kit 中继续,它将定期更新并支持所有 zip_tricks 功能(以及更多)。感谢您成为 zip_tricks 社区的一员!
允许从 Ruby 流式传输、非倒带 ZIP 文件输出。
最初是作为 zipline 的精神继承者而编写的,现在自豪地在引擎盖下为它提供动力。
允许您将 ZIP 存档写入文件、套接字、字符串或数组,而无需在任何时候将其倒回。可用于创建非常大的 ZIP 档案以立即发送给客户,或用于编写大型 ZIP 档案而无需内存膨胀。
zip_tricks 目前可以处理我们所有的压缩需求(每天生成数百万个 ZIP 文件),因此我们非常有信心它与大量取消归档的最终用户应用程序广泛兼容。
Ruby 2.1+ 语法支持(带有默认值的关键字参数)和一个可用的 zlib(所有这些也适用于 jRuby)。由于IO#seek
的参数限制为 32 位大小,jRuby 在使用读取器方法时可能会遇到问题。
最简单的方法是将ZipTricks::RailsStreaming
模块包含到控制器中。
class ZipsController < ActionController :: Base
include ZipTricks :: RailsStreaming
def download
zip_tricks_stream do | zip |
zip . write_deflated_file ( 'report1.csv' ) do | sink |
CSV ( sink ) do | csv_write |
csv_write << Person . column_names
Person . all . find_each do | person |
csv_write << person . attributes . values
end
end
end
zip . write_deflated_file ( 'report2.csv' ) do | sink |
...
end
end
end
end
如果您想要更多便利,您还可以使用 zipline,它将通过 HTTP 自动处理和传输附件(Carrierwave、Shrine、ActiveStorage)和远程对象。
基本用例是动态压缩。一些数据将由 Zlib 压缩器缓冲,但内存膨胀将受到很大限制。数据将以相当规律的间隔写入目的地。 Deflate 压缩最适合文本文件等内容。
out = my_tempfile # can also be a socket
ZipTricks :: Streamer . open ( out ) do | zip |
zip . write_stored_file ( 'mov.mp4.txt' ) do | sink |
File . open ( 'mov.mp4' , 'rb' ) { | source | IO . copy_stream ( source , sink ) }
end
zip . write_deflated_file ( 'long-novel.txt' ) do | sink |
File . open ( 'novel.txt' , 'rb' ) { | source | IO . copy_stream ( source , sink ) }
end
end
不幸的是,使用这种方法无法计算输出的 ZIP 文件的大小,因为您不知道压缩数据段有多大。
要从 ZipTricks“拉取”数据,您可以创建一个OutputEnumerator
对象,该对象将逐块生成二进制块,并应用一定量的缓冲。由于此OutputEnumerator
响应#each
并生成字符串,因此它也可以(并且应该!)用作 Rack 响应主体。将其返回到您的网络服务器,您将获得 ZIP 流式传输。您提供给OutputEnumerator
的块仅在您的响应正文开始迭代后才会开始执行 - 当实际将响应发送到客户端时(除非您使用的是缓冲 Rack Web 服务器,例如 Webrick)。
body = ZipTricks :: Streamer . output_enum do | zip |
zip . write_stored_file ( 'mov.mp4' ) do | sink | # Those MPEG4 files do not compress that well
File . open ( 'mov.mp4' , 'rb' ) { | source | IO . copy_stream ( source , sink ) }
end
zip . write_deflated_file ( 'long-novel.txt' ) do | sink |
File . open ( 'novel.txt' , 'rb' ) { | source | IO . copy_stream ( source , sink ) }
end
end
[ 200 , { } , body ]
使用SizeEstimator
计算生成的存档的正确大小。
# Precompute the Content-Length ahead of time
bytesize = ZipTricks :: SizeEstimator . estimate do | z |
z . add_stored_entry ( filename : 'myfile1.bin' , size : 9090821 )
z . add_stored_entry ( filename : 'myfile2.bin' , size : 458678 )
end
# Prepare the response body. The block will only be called when the response starts to be written.
zip_body = ZipTricks :: RackBody . new do | zip |
zip . add_stored_entry ( filename : "myfile1.bin" , size : 9090821 , crc32 : 12485 )
zip << read_file ( 'myfile1.bin' )
zip . add_stored_entry ( filename : "myfile2.bin" , size : 458678 , crc32 : 89568 )
zip << read_file ( 'myfile2.bin' )
end
[ 200 , { 'Content-Length' => bytesize . to_s } , zip_body ]
您不必通过 Streamer 对象“提供”放入存档中的文件的所有内容。如果您的用例的写入目标是Socket
(例如,您正在使用机架劫持进行写入)并且您预先知道文件的元数据(未压缩文件的 CRC32 和大小),则可以使用直接写入该套接字一些加速写入技术,并且仅使用Streamer写出ZIP元数据。
# io has to be an object that supports #<<
ZipTricks :: Streamer . open ( io ) do | zip |
# raw_file is written "as is" (STORED mode).
# Write the local file header first..
zip . add_stored_entry ( filename : "first-file.bin" , size : raw_file . size , crc32 : raw_file_crc32 )
# Adjust the ZIP offsets within the Streamer
zip . simulate_write ( my_temp_file . size )
# ...and then send the actual file contents bypassing the Streamer interface
io . sendfile ( my_temp_file )
end
查看项目根目录下的examples/
目录。这将使您很好地了解该库支持的各种用例。
BlockCRC32
以流方式计算 IO 的 CRC32 校验和。与使用原始 Zlib 库函数相比,它稍微方便一些。
crc = ZipTricks :: StreamCRC32 . new
crc << next_chunk_of_data
...
crc . to_i # Returns the actual CRC32 value computed so far
...
# Append a known CRC32 value that has been computed previosuly
crc . append ( precomputed_crc32 , size_of_the_blob_computed_from )
如果整个 IO 对象响应#eof?
您还可以计算它的 CRC32。 :
crc = ZipTricks :: StreamCRC32 . from_io ( file ) # Returns an Integer
该库包含一个阅读器模块,使用它来看看有什么可能。它不是一个完整的 ZIP 阅读器,但它是为特定目的(远程存储的 ZIP 文件的高度并行解包)而设计的,因此它可以很好地执行其功能。请注意使用未经正式验证的 ZIP 阅读器(我们的尚未经过正式验证)的安全隐患。
main
以确保该功能尚未实现或错误尚未修复。版权所有 (c) 2020 WeTransfer。
zip_tricks
是在希波克拉底许可证的条件下分发的,请参阅 LICENSE.txt 了解更多详细信息。如果您的用例不接受此许可证,我们仍然维护 MIT 许可证下的 4.x 版本树,请参阅 https://rubygems.org/gems/zip_tricks/versions 了解更多信息。请注意,我们仅向后移植一些性能优化和关键错误修复,而不是该树的新功能。