2011-05-16 168 views
4

我知道如何使用rubyzip检索正常压缩文件的内容。但是我解压缩zip文件夹的内容时遇到了麻烦,我希望你们中的任何人都能帮助我。如何使用rubyzip解压缩压缩文件夹

这是我使用解压缩代码:

Zip::ZipFile::open(@file_location) do |zip| 
zip.each do |entry| 
    next if entry.name =~ /__MACOSX/ or entry.name =~ /\.DS_Store/ or !entry.file? 
    logger.debug "#{entry.name}" 
    @data = File.new("#{Rails.root.to_s}/tmp/#{entry.name}") 
end 
end 

entry.name给我的zip文件中的文件名。这与一个正常的zipfile完美配合。但是,当从文件夹创建zipfile时,条目的名称就像是:test-folder/test.pdf。当我然后尝试创建该文件时,它告诉我无法找到该文件。这可能是因为它位于zip中的“测试”文件夹内。

如果我将条目检查为文件夹,则无法找到任何文件夹。所以我认为解决方案是将条目作为流读取,然后将其另存为文件。入门很容易,但如何将其保存为文件?这是我到目前为止。

Zip::ZipFile::open(@file_location) do |zip| 
zip.each do |entry| 
    next if entry.name =~ /__MACOSX/ or entry.name =~ /\.DS_Store/ or !entry.file? 
    logger.debug "#{entry.name}" 
    @data = entry.get_input_stream.read 
    # How do i create a file from a stream? 
end 
end 

基本上我的问题是:如何从流中创建文件?还是有比我更容易的方法吗?

===编辑=== 我用回形针来存储文件。

回答

0

我认为你的问题不在于你是否需要从流中写入文件。基本上,如果您拨打File.newwill create a new IO-StreamFileIO的子类)。因此,无论你想从zip文件流中进行处理,都应该使用普通文件。

当你说

当我再尝试创建的文件,它告诉我的文件无法找到

我觉得会发生什么是父目录的文件你想创建不存在(在你的情况下,test-folder)。你想要做的是类似的东西(未测试):

Zip::ZipFile::open(@file_location) do |zip| 
zip.each do |entry| 
    next if entry.name =~ /__MACOSX/ or entry.name =~ /\.DS_Store/ or !entry.file? 
    logger.debug "#{entry.name}" 
    FileUtils::mkdir_p(File.dirname(entry.name)) # might want to check if it already exists  
    @data = File.new("#{Rails.root.to_s}/tmp/#{entry.name}") 
end 
end 
+0

我试过你的代码,但它只在我的项目的根目录下创建项目的父文件夹。我仍然无法访问它自己的条目。这实际上是一个Errno :: ENOENT - 我想我应该提到这一点。 thx tho – grub4r 2011-05-16 22:03:05

0

我解决它通过使用流和创建一个StringIO的。这里是

Zip::ZipFile::open(@file_location) do |zip| 
zip.each do |entry| 
    next if entry.name =~ /__MACOSX/ or entry.name =~ /\.DS_Store/ or !entry.file? 

    begin 
    # the normal unzip-code 
    rescue Errno::ENOENT 
    # when the entry can not be found 
    @data = entry.get_input_stream.read 
    @file = StringIO.new(@data) 
    @file.class.class_eval { attr_accessor :original_filename, :content_type } 
    @file.original_filename = entry.name 
    @file.content_type = MIME::Types.type_for(entry.name) 

    # save it/whatever 
    end 
end 
end 
+0

第一行应该是: 'Zip :: ZipFile.open(@file_location)do | zip |' – lightyrs 2013-08-12 20:33:06

2

我发现基于jhwist的一个更简单的方法工作确定代码:

Zip::File.open(@file_location) do |zipfile| 
    zipfile.each do |entry| 
    # The 'next if...' code can go here, though I didn't use it 
    unless File.exist?(entry.name) 
     FileUtils::mkdir_p(File.dirname(entry.name)) 
     zipfile.extract(entry, entry.name) 
    end 
    end 
end 

的条件显然是可选的,但是没有它,如果它试图重写代码会产生错误一个现有的文件。

+0

这种方法不保留文件的权限。提取后如何保留权限? – itsh 2015-09-01 22:47:33