使用rubyzip将文件和嵌套目录添加到zipoutputstream

时间:2010-02-24 00:48:39

标签: ruby rubyzip

我正在努力让rubyzip将目录附加到zipoutputstream。 (我想要输出流,所以我可以从rails控制器发送它)。我的代码遵循以下示例:

http://info.michael-simons.eu/2008/01/21/using-rubyzip-to-create-zip-files-on-the-fly/

当修改为包含要添加的文件列表中的目录时,我收到以下错误:

非常感谢任何帮助。

更新

在尝试了一些解决方案后,我在zipruby上取得了最大的成功,它有一个干净的api和很好的例子:http://zipruby.rubyforge.org/

4 个答案:

答案 0 :(得分:8)

Zip::ZipFile.open(path, Zip::ZipFile::CREATE) do |zip|
  songs.each do |song|
    zip.add "record/#{song.title.parameterize}.mp3", song.file.to_file.path
  end
end

答案 1 :(得分:4)

OOOOOuuhhh ...你绝对想要ZIPPY。它是一个Rails插件,它提取了rubyzip中的许多复杂性,并允许您创建您正在谈论的内容,包括目录(我记得)。

你走了:

http://github.com/toretore/zippy

直接来自zippy网站:

Example controller:
def show
  @gallery = Gallery.find(params[:id])
  respond_to do |format|
    format.html
    format.zip
  end
end

Example view:
zip['description.txt'] = @gallery.description
@gallery.photos.each do |photo|
  zip["photo_#{photo.id}.png"] = File.open(photo.url)
end

修改:修改每个用户评论:

嗯......使用Zippy的整个目标是使用红宝石拉链变得更加容易。 雅可能想要第二次(或第一次)看......

以下是如何使用目录制作目录:

some_var = Zippy.open('awsum.zip') do |zip|
  %w{dir_a dir_b dir_c diri}.each do |dir|  
    zip["bin/#{dir}/"]
  end
end

...

send_file some_var, :file_name => ...

答案 2 :(得分:3)

Zippy将为此工作。可能有一种更酷的方法可以做到这一点,但由于基本上没有文档,这就是我想出的用于在Rakefile中以Zippy递归复制目录。这个Rakefile用在Rails环境中,所以我把gem需求放在我的Gemfile中:

#Gemfile
source 'http://rubygems.org'
gem 'rails'
gem 'zippy'

这是Rakefile

#Rakefile
def add_file( zippyfile, dst_dir, f )
  zippyfile["#{dst_dir}/#{f}"] = File.open(f)
end

def add_dir( zippyfile, dst_dir, d )
  glob = "#{d}/**/*"
  FileList.new( glob ).each { |f|
    if (File.file?(f))
      add_file zippyfile, dst_dir, f
    end
  }
end

task :myzip do
  Zippy.create 'my.zip' do |z|
    add_dir z, 'my', 'app'
    add_dir z, 'my', 'config'
    #...
    add_file z, 'my', 'config.ru'
    add_file z, 'my', 'Gemfile'
    #...
  end
end

现在我可以像这样使用它:

C:\> cd my
C:\my> rake myzip

它将生成my.zip,其中包含一个名为“my”的内部目录,其中包含所选文件和目录的副本。

答案 3 :(得分:2)

我能够使用original article中使用的相同ZipOutputStream获取目录。

我所要做的就是在调用zos.put_next_entry时添加目录。

例如:

require 'zip/zip'
require 'zip/zipfilesystem'

t = Tempfile.new("some-weird-temp-file-basename-#{request.remote_ip}")
# Give the path of the temp file to the zip outputstream, it won't try to open it as an archive.
Zip::ZipOutputStream.open(t.path) do |zos|
  some_file_list.each do |file|
    # Create a new entry with some arbitrary name
    zos.put_next_entry("myfolder/some-funny-name.jpg") # Added myfolder/
    # Add the contents of the file, don't read the stuff linewise if its binary, instead use direct IO
    zos.print IO.read(file.path)
  end
end
# End of the block  automatically closes the file.
# Send it using the right mime type, with a download window and some nice file name.
send_file t.path, :type => 'application/zip', :disposition => 'attachment', :filename => "some-brilliant-file-name.zip"
# The temp file will be deleted some time...
t.close

我刚刚将zos.put_next_entry('some-funny-name.jpg')更改为zos.put_next_entry('myfolder/some-funny-name.jpg'),并且生成的zipfile有一个名为myfolder的嵌套文件夹,其中包含这些文件。