zip_tricks는 추가 업데이트나 지원을 받지 않으며 더 이상 유지 관리되지 않습니다. zip_tricks의 이야기는 정기적인 업데이트를 받고 모든 zip_tricks 기능(및 그 이상)을 지원하게 될 zip_kit에서 계속됩니다. 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
좀 더 편리함을 원한다면 HTTP를 통해 첨부 파일(Carrierwave, Shrine, ActiveStorage)과 원격 개체를 자동으로 처리하고 스트리밍하는 zipline을 사용할 수도 있습니다.
기본 사용 사례는 즉시 압축입니다. 일부 데이터는 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
에 제공하는 블록은 응답 본문이 반복되기 시작한 후에만 실행을 시작합니다. 실제로 클라이언트에 응답을 보낼 때입니다(Webrick과 같은 버퍼링 Rack 웹 서버를 사용하지 않는 한).
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 )
#eof?
에 응답하는 경우 전체 IO 객체에 대한 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를 참조하세요. 일부 성능 최적화 및 중요한 버그 수정만 백포트하고 해당 트리의 새로운 기능은 백포트하지 않습니다.