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 以了解更多資訊。請注意,我們僅向後移植一些效能優化和關鍵錯誤修復,而不是該樹的新功能。