ruby stream tar gz

Ruby streaming tar/gz



(2)

Básicamente quiero transmitir datos desde la memoria a un formato tar / gz (posiblemente varios archivos en el tar, pero NUNCA TOCAR LA HARDDRIVE, ¡solo la transmisión!), Luego transmitirlos a otro lugar (un cuerpo de solicitud HTTP en mi caso).

Alguien sabe de una biblioteca existente que puede hacer esto? ¿Hay algo en Rails?

libarchive-ruby es solo un contenedor C y parece que dependerá mucho de la plataforma (¿los documentos quieren que compile como un paso de instalación ?!).

SOLUCIÓN:

require ''zlib'' require ''rubygems/package'' tar = StringIO.new Gem::Package::TarWriter.new(tar) { |writer| writer.add_file("a_file.txt", 0644) { |f| (1..1000).each { |i| f.write("some text/n") } } writer.add_file("another_file.txt", 0644) { |f| f.write("some more text/n") } } tar.seek(0) gz = Zlib::GzipWriter.new(File.new(''this_is_a_tar_gz.tar.gz'', ''wb'')) # Make sure you use ''wb'' for binary write! gz.write(tar.read) tar.close gz.close

¡Eso es! Puede intercambiar el archivo en el GzipWriter con cualquier IO para mantenerlo en línea. ¡Cookies para dw11wtq!


Basado en la solución que OP escribió, escribí la función de archivo tgz totalmente en la memoria lo que quiero usar para POSTAR al servidor web.

# Create tar gz archive file from files, on the memory. # Parameters: # files: Array of hash with key "filename" and "body" # Ex: [{"filename": "foo.txt", "body": "This is foo.txt"},...] # # Return:: tar_gz archived image as string def create_tgz_archive_from_files(files) tar = StringIO.new Gem::Package::TarWriter.new(tar){ |tar_writer| files.each{|file| tar_writer.add_file(file[''filename''], 0644){|f| f.write(file[''body'']) } } } tar.rewind gz = StringIO.new('''', ''r+b'') gz.set_encoding("BINARY") gz_writer = Zlib::GzipWriter.new(gz) gz_writer.write(tar.read) tar.close gz_writer.finish gz.rewind tar_gz_buf = gz.read return tar_gz_buf end


Eche un vistazo a la clase TarWriter en rubygems: http://rubygems.rubyforge.org/rubygems-update/Gem/Package/TarWriter.html solo opera en una secuencia IO, que puede ser un StringIO.

tar = StringIO.new Gem::Package::TarWriter.new(tar) do |writer| writer.add_file("hello_world.txt", 0644) { |f| f.write("Hello world!/n") } end tar.seek(0) p tar.read #=> mostly padding, but a tar nonetheless

También proporciona métodos para agregar directorios si necesita un diseño de directorio en el tarball.

Como referencia, puede lograr el gzipping con IO.popen , simplemente IO.popen / sacando los datos del proceso del sistema:

http://www.ruby-doc.org/core-1.9.2/IO.html#method-c-popen

El gzip se vería así:

gzippped_data = IO.popen("gzip", "w+") do |gzip| gzip.puts "Hello world!" gzip.close_write gzip.read end # => "/u001F/x8B/b/u0000/xFD/u001D/xA2N/u0000/u0003/xF3H/xCD/xC9/xC9W(/xCF//xCAIQ/xE4/u0002/u0000A䩲/r/u0000/u0000/u0000"