لن تتلقى 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، لكن تضخم الذاكرة سيكون مقيدًا للغاية. سيتم كتابة البيانات إلى الوجهة على فترات منتظمة إلى حد ما. سيعمل ضغط التفريغ بشكل أفضل مع أشياء مثل الملفات النصية.
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 مؤقتًا، مثل 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 للإدخال/الإخراج بطريقة متدفقة. إنه أكثر ملاءمة لهذا الغرض قليلاً من استخدام وظائف مكتبة 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 لكائن الإدخال/الإخراج بأكمله إذا استجاب لـ #eof?
:
crc = ZipTricks :: StreamCRC32 . from_io ( file ) # Returns an Integer
تحتوي المكتبة على وحدة قارئ، العب بها لترى ما هو ممكن. إنه ليس قارئ ZIP كاملاً ولكنه مصمم لغرض محدد (التفريغ المتوازي للغاية لملفات ZIP المخزنة عن بعد)، وعلى هذا النحو فهو يؤدي وظيفته بشكل جيد. يرجى الحذر من الآثار الأمنية المترتبة على استخدام برامج قراءة ZIP التي لم يتم التحقق منها رسميًا (لم يتم التحقق منها).
main
للتأكد من عدم تنفيذ الميزة أو عدم إصلاح الخطأ بعد.حقوق الطبع والنشر (ج) 2020 WeTransfer.
يتم توزيع zip_tricks
بموجب شروط ترخيص أبقراط، راجع LICENSE.txt لمزيد من التفاصيل. إذا كان هذا الترخيص غير مقبول لحالة الاستخدام الخاصة بك، فإننا لا نزال نحتفظ بشجرة الإصدار 4.x التي تظل ضمن ترخيص MIT، راجع https://rubygems.org/gems/zip_tricks/versions لمزيد من المعلومات. لاحظ أننا ندعم فقط بعض تحسينات الأداء وإصلاحات الأخطاء المهمة ولكن ليس الميزات الجديدة لتلك الشجرة.