Как я могу создать zip файл без сохранения на диск с Ruby?
Я создал много файлов PDF в памяти, и я хочу сжать их в один ZIP файл, прежде чем отправлять его в виде вложения электронной почты. Я посмотрел на Rubyzip, и это не позволяет мне создать zip файл, не сохраняя его на диске (возможно, я ошибаюсь).
Есть ли способ сжать этот файл без создания временного файла?
Ответы
Ответ 1
У меня была аналогичная проблема, которую я решил использовать с камнем rubyzip и объектом stringio.
Оказывается, rubyzip предоставляет метод, возвращающий объект stringio: ZipOutputStream.write_buffer
.
Вы можете создать структуру zip файла, как вам нравится, с помощью put_next_entry
и написать, и как только вы закончите, вы можете перемотать строку и прочитать двоичные данные с помощью 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) (Java-сервер HotSpot (TM) 64-разрядный сервер VM 1.6.0_29) [Windows Server 2008-amd64-java] )
Следующий пример работает для 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
Ответ 2
Ruby поставляется с очень удобной библиотекой StringIO
- это может использоваться для использования String в качестве выходного IO-объекта или поддельного чтения файла, поддерживаемого String.
Проблема заключается в том, что RubyZip не поддерживает прямое получение объекта IO при создании Zip::ZipOutputStream
, но если вы посмотрите на реализацию initialize
и в зависимости от вашей готовности экспериментировать, вы можете расширьте класс и позвольте ему взять объект IO или имя файла в конструкторе.
Ответ 3
Есть две библиотеки RubyZip, которые я смог найти.
Библиотека Chilkat позволяет создавать zip файл в памяти вместо того, чтобы автоматически записывать его на диск, как показано в этих ссылках: Zip to Memory, Почтовый индекс из данных памяти
Один из SourceForge, с другой стороны, может предоставить возможность архивирования файла в памяти, но я не совсем уверен, так как я очень новичок в рубине. Rubyzip SourceForge основан на java.util.zip
, который привел к тому, что он имеет класс под названием ZipOutputStream
. Я не знаю, насколько хороша реализация rubyzip, но при реализации java.util.zip
OutputStream
может быть установлено значение ByteArrayOutputStream
, FileOutputStream
, FilterOutputStream
, ObjectOutputStream
, OutputStream
, PipedOutputStream
....
Если это верно для реализации rubyzip, тогда нужно использовать ZipOutputStream
для передачи в ByteArrayOutputStream
сортировок, которые приведут к его выводу в память.
Если он не существует в rubyzip, тогда я уверен, что вы всегда можете написать свою собственную реализацию и отправить ее для включения в rubyzip, увидев, что это open source.
Ответ 4
Если вы работаете в Linux, и в зависимости от того, сколько у вас RAM и насколько велики ваши файлы, вы всегда можете использовать tmpfs (shared memory). Затем будут работать методы на основе диска rubyzip. http://www.mjmwired.net/kernel/Documentation/filesystems/tmpfs.txt