使用 ruby​​zip 将文件和嵌套目录添加到 zipoutputstream

发布于 2024-08-22 21:59:18 字数 567 浏览 2 评论 0原文

我正在努力让 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/

I'm struggling with getting rubyzip to append directories to a zipoutputstream. (I want the output stream so I can send it from a rails controller). My code follows this example:

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

When modified to include directories in the list of files to add I get the following error:

Any help would be greatly appreciated.

UPDATE

After trying a number of solutions I had best success with zipruby which has a clean api and good examples: http://zipruby.rubyforge.org/.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

苯莒 2024-08-29 21:59:18
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
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
丶视觉 2024-08-29 21:59:18

OOOOuuuhh...你肯定想要 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 => ...

OOOOOuuuhh...you DEFINITELY want ZIPPY. It's a Rails plugin that abstracts a lot of the complexity in rubyzip, and lets you create what you're talking about, including directories (from what I recall).

Here you go:

http://github.com/toretore/zippy

And direct from the zippy site:

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

edit: Amending per user comment:

Hmm...the whole objective of using Zippy is to make it a whole lot easier to use ruby zip.
Ya might want to take a second (or first) look...

Here's how to make a directory with directories:

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 => ...
就像说晚安 2024-08-29 21:59:18

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' 包含所选文件和目录的副本。

Zippy will work for this. There may be a more cool way to do this but since there are essentially no docs, here's what I came up with for recursively copying directories with Zippy in a Rakefile. This Rakefile is used in a Rails environment so I put gem requirements in my Gemfile:

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

And this is the 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

Now I can use it like this:

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

and it will produce my.zip which contains an inner directory called 'my' with copies of selected files and directories.

回忆那么伤 2024-08-29 21:59:18

我能够让目录使用 原始文章

我所要做的就是在调用 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'),生成的 zip 文件有一个名为 myfolder 的嵌套文件夹,其中包含这些文件。

I was able to get directories working with the same ZipOutputStream used in the original article.

All I had to do was add the directory when calling zos.put_next_entry.

For example:

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

I just changed zos.put_next_entry('some-funny-name.jpg') to zos.put_next_entry('myfolder/some-funny-name.jpg'), and the resulting zipfile had a nested folder called myfolder that contained the files.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文