【问题标题】:Using rubyzip to add files and nested directories to a zipoutputstream使用 ruby​​zip 将文件和嵌套目录添加到 zipoutputstream
【发布时间】:2011-01-20 08:15:05
【问题描述】:

我正在努力让 ruby​​zip 将目录附加到 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/

【问题讨论】:

  • 伟大的工作找到了 zipruby,拯救了我的一天!

标签: ruby rubyzip


【解决方案1】:

我能够使目录与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'),生成的压缩文件有一个名为myfolder 的嵌套文件夹,其中包含这些文件。

【讨论】:

  • 您的方法效果很好,谢谢!差点切换到zipruby,不过好像没维护了。
【解决方案2】:

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】:
    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
    

    【讨论】:

      【解决方案4】:

      OOOOuuuuhh……你肯定想要 ZIPPY。这是一个 Rails 插件,它抽象了 ruby​​zip 中的许多复杂性,并允许您创建您正在谈论的内容,包括目录(据我回忆)。

      给你:

      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 的全部目的是让使用 ruby​​ zip 变得更容易。 你可能想再看一下(或第一次)...

      以下是使用目录创建目录的方法:

      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 => ...
      

      【讨论】:

      • 谢谢,这看起来不错,但文档有点害羞,我现在没有时间深入研究源代码。那么,例如,我将如何创建一个 zip 流并添加一个目录目录?另外,我需要使用 sendfile 而不是自定义 mime 类型。谢谢。
      • 修正了答案,以防您有兴趣。
      • 抱歉,我发现这颗宝石非常辛苦。我将尝试其他几个可以以我想要的方式流式传输新创建的 zip 的方法。
      • @btelles,Zippy 看起来不错,但确实没有文档。您是否碰巧知道任何指向示例代码的链接?您创建(空)目录的示例是一个好的开始,但我想做的是递归地复制一个包含现有文件和子目录的目录。我还没有找到如何复制单个文件的示例(只有如何编写新文件)。
      • 抱歉,我不知道任何链接,但是您可能会发现规范至少有点帮助。 :-/
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-15
      • 1970-01-01
      相关资源
      最近更新 更多