Как я могу сгенерировать zip-файл без сохранения на диске с Ruby? - PullRequest
36 голосов
/ 09 марта 2010

Я сгенерировал много файлов PDF в памяти и хочу сжать их в один zip-файл перед отправкой в ​​виде вложения электронной почты. Я посмотрел на Rubyzip, и он не позволяет мне создать файл zip без сохранения его на диск (возможно, я ошибаюсь).

Есть ли способ сжать эти файлы без создания временного файла?

Ответы [ 4 ]

48 голосов
/ 15 марта 2012

У меня была похожая проблема, которую я решил с помощью гема rubyzip и объекта stringio. Оказывается, что rubyzip предоставляет метод, который возвращает объект stringio: ZipOutputStream.write_buffer.

Вы можете создать структуру zip-файла по своему усмотрению, используя put_next_entry и писать, и как только вы закончите, вы можете перемотать stringio и прочитать двоичные данные, используя sysread.

См. Следующий простой пример (работает для rubyzip 0.9.X)

require 'zip/zip'
stringio = Zip::OutputStream.write_buffer do |zio|
  zio.put_next_entry("test.txt")
  zio.write "Hello world!"
end
stringio.rewind
binary_data = stringio.sysread

Протестировано на jruby 1.6.5.1 (ruby-1.9.2-p136) (2011-12-27 1bf37c2) (64-разрядный сервер Java HotSpot (TM), виртуальная машина 1.6.0_29) [Windows Server 2008-amd64-java] ) * +1010 *

Следующий пример работает для rubyzip> = 1.0.0

require 'rubygems'    
require 'zip'
stringio = Zip::OutputStream.write_buffer do |zio|
  zio.put_next_entry("test.txt")
  zio.write "Hello world!"
end
binary_data = stringio.string

Протестировано на jruby 1.7.22 (1.9.3p551) 2015-08-20 c28f492 на 64-битном сервере OpenJDK VM 1.7.0_79-b14 + jit [linux-amd64] и rubyzip gem 1.1.7

5 голосов
/ 12 апреля 2010

Ruby поставляется с очень удобной библиотекой StringIO - ее можно использовать для использования String в качестве объекта ввода-вывода или для фальсификации чтения файла, поддерживаемого String.

Проблема здесь заключается в том, что RubyZip не поддерживает непосредственный взятие объекта ввода-вывода при создании Zip::ZipOutputStream, но если вы посмотрите на реализацию initialize и, в зависимости от вашей готовности экспериментировать, вы сможете расширить класс и разрешить ему принимать либо объект ввода-вывода, либо имя файла в конструкторе.

1 голос
/ 09 марта 2010

Мне удалось найти две библиотеки RubyZip.

  1. Библиотека Chilkat Ruby Zip
  2. rubyzip на Sourceforge

Библиотека Chilkat определенно позволяет создавать zip-файлы в памяти вместо автоматической записи их на диск, как показано в следующих ссылках: Zip to Memory , Zip-данные из данных памяти

С другой стороны, в SourceForge может быть возможность архивирования файла в памяти, но я не совсем уверен, так как я очень плохо знаком с ruby. SourceForge rubyzip основан на java.util.zip, в результате чего класс имеет класс ZipOutputStream. Я не знаю, насколько хороша реализация rubyzip, но с реализацией java.util.zip OutputStream можно установить на ByteArrayOutputStream, FileOutputStream, FilterOutputStream, ObjectOutputStream, OutputStream, PipedOutputStream ....

Если это справедливо для реализации rubyzip, тогда нужно использовать ZipOutputStream для передачи ByteArrayOutputStream сортов, что приведет к его выводу в память.

Если его нет в rubyzip, то я уверен, что вы всегда можете написать свою собственную реализацию и представить ее для включения в rubyzip, поскольку она имеет открытый исходный код.

0 голосов
/ 12 апреля 2010

Если вы работаете в Linux, и в зависимости от того, сколько у вас ОЗУ и размер ваших файлов, вы всегда можете использовать tmpfs (разделяемая память). Затем будут работать методы, основанные на диске rubyzip. http://www.mjmwired.net/kernel/Documentation/filesystems/tmpfs.txt

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...