zip_tricks จะไม่ได้รับการอัปเดตหรือการสนับสนุนเพิ่มเติม และจะไม่ได้รับการบำรุงรักษาอีกต่อไป เรื่องราวของ zip_tricks ดำเนินต่อไปใน zip_kit ซึ่งกำลังจะได้รับการอัปเดตเป็นประจำและรองรับฟังก์ชัน zip_tricks ทั้งหมด (และอีกมากมาย) ขอบคุณที่เป็นส่วนหนึ่งของชุมชน zip_tricks!
อนุญาตให้สตรีมเอาต์พุตไฟล์ ZIP แบบไม่กรอกลับจาก Ruby
เขียนครั้งแรกและเป็นผู้สืบทอดทางจิตวิญญาณของ zipline และตอนนี้ภูมิใจในการขับเคลื่อนมันภายใต้ประทุน
ช่วยให้คุณสามารถเขียนไฟล์ ZIP ลงในไฟล์ ซ็อกเก็ต สตริง หรืออาร์เรย์ โดยไม่ต้องกรอกลับเมื่อใดก็ได้ ใช้สำหรับการสร้างไฟล์ ZIP ขนาดใหญ่มากเพื่อส่งออกไปยังไคลเอนต์ทันที หรือสำหรับการเขียนไฟล์ ZIP ขนาดใหญ่โดยไม่มีการเพิ่มหน่วยความจำ
ปัจจุบัน zip_tricks จัดการความต้องการซิปทั้งหมดของเรา (ไฟล์ ZIP หลายล้านไฟล์ที่สร้างขึ้นต่อวัน) ดังนั้นเราจึงค่อนข้างมั่นใจว่าสามารถใช้งานร่วมกับแอปพลิเคชันผู้ใช้ปลายทางที่ไม่เก็บถาวรจำนวนมากได้อย่างกว้างขวาง
การสนับสนุนไวยากรณ์ Ruby 2.1+ (อาร์กิวเมนต์คำหลักที่มีค่าเริ่มต้น) และ zlib ที่ใช้งานได้ (ทั้งหมดมีให้สำหรับ jRuby เช่นกัน) jRuby อาจประสบปัญหาเมื่อใช้วิธีการอ่านเนื่องจากอาร์กิวเมนต์ของ IO#seek
ถูกจำกัดไว้ที่ขนาด 32 บิต
วิธีที่ง่ายที่สุดคือการรวมโมดูล 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 ซึ่งจะประมวลผลและสตรีมไฟล์แนบโดยอัตโนมัติ (Carrierwave, Shrine, ActiveStorage) และวัตถุระยะไกลผ่าน HTTP
กรณีการใช้งานขั้นพื้นฐานคือการบีบอัดข้อมูลได้ทันที ข้อมูลบางอย่างจะถูกบัฟเฟอร์โดย Zlib deflater แต่การพองตัวของหน่วยความจำจะถูกจำกัดอย่างมาก ข้อมูลจะถูกเขียนไปยังปลายทางในช่วงเวลาที่ค่อนข้างสม่ำเสมอ การบีบอัดแบบยุบจะทำงานได้ดีที่สุดกับสิ่งต่างๆ เช่น ไฟล์ข้อความ
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
และให้ค่า Strings จึงสามารถใช้ได้ (และควร!) เป็นเนื้อหาการตอบสนองของ Rack ส่งคืนไปยังเว็บเซิร์ฟเวอร์ของคุณแล้วคุณจะสตรีม ZIP ของคุณ บล็อกที่คุณให้กับ OutputEnumerator
จะเริ่มทำงานก็ต่อเมื่อเนื้อหาการตอบสนองของคุณเริ่มถูกวนซ้ำ - เมื่อส่งการตอบกลับไปยังไคลเอนต์จริง ๆ (เว้นแต่ว่าคุณกำลังใช้เว็บเซิร์ฟเวอร์ชั้นวางบัฟเฟอร์เช่น 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
(เช่น คุณกำลังเขียนโดยใช้ Rack hijack) และคุณทราบข้อมูลเมตาของไฟล์ล่วงหน้า (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
คำนวณการตรวจสอบ CRC32 ของ IO ในรูปแบบการสตรีม สะดวกกว่าการใช้ฟังก์ชันไลบรารี 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 )
คุณยังสามารถคำนวณ CRC32 สำหรับออบเจ็กต์ IO ทั้งหมดได้ หากมันตอบสนองต่อ #eof?
-
crc = ZipTricks :: StreamCRC32 . from_io ( file ) # Returns an Integer
ห้องสมุดมีโมดูลตัวอ่าน ลองเล่นกับมันเพื่อดูว่าอะไรเป็นไปได้ มันไม่ใช่โปรแกรมอ่าน ZIP ที่สมบูรณ์ แต่ได้รับการออกแบบมาเพื่อวัตถุประสงค์เฉพาะ (การแตกไฟล์ ZIP ที่จัดเก็บจากระยะไกลแบบขนานกัน) และด้วยเหตุนี้จึงทำให้ฟังก์ชันทำงานได้ค่อนข้างดี โปรดระวังผลกระทบด้านความปลอดภัยของการใช้โปรแกรมอ่าน ZIP ที่ยังไม่ได้รับการยืนยันอย่างเป็นทางการ (ของเรายังไม่ได้รับการตรวจสอบ)
main
ล่าสุดเพื่อให้แน่ใจว่าคุณสมบัติยังไม่ได้ถูกนำมาใช้หรือจุดบกพร่องยังไม่ได้รับการแก้ไขลิขสิทธิ์ (c) 2020 WeTransfer
zip_tricks
ได้รับการเผยแพร่ภายใต้เงื่อนไขของใบอนุญาต Hippocratic ดู LICENSE.txt สำหรับรายละเอียดเพิ่มเติม หากใบอนุญาตนี้ไม่ได้รับการยอมรับสำหรับกรณีการใช้งานของคุณ เรายังคงรักษาแผนผังเวอร์ชัน 4.x ซึ่งยังคงอยู่ภายใต้ใบอนุญาต MIT โปรดดู https://rubygems.org/gems/zip_tricks/versions สำหรับข้อมูลเพิ่มเติม โปรดทราบว่าเราสนับสนุนเฉพาะการปรับปรุงประสิทธิภาพและการแก้ไขข้อบกพร่องที่สำคัญบางอย่างเท่านั้น แต่ไม่ใช่คุณลักษณะใหม่ในแผนผังนั้น