Подтвердить что ты не робот

Как я могу создать zip файл без сохранения на диск с Ruby?

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

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

4b9b3361

Ответ 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