【问题标题】:How to unzip a file in Ruby on Rails?如何在 Ruby on Rails 中解压缩文件?
【发布时间】:2020-02-18 02:35:44
【问题描述】:

我正在使用 Ruby on Rails 将文件上传到服务器

通常,它是一个文本文件,我将它保存在模型中作为提交 ActiveRecord 中的“文件”字段以及提交标题等其他字段。

但是,用户也可以提交 zip 文件。在这种情况下,应该解压缩 zip 文件,并为 zip 中的每个文件创建一个新的提交,使用相同的文本字段,但当前文件。

我怎样才能做到这一点?

我在网上查看了解压缩示例,但大多数使用目录将文件解压缩到。我不确定是否需要像 SubmissionsController 的当前 create 方法那样,接收到一个文件对象,并且我假设在调用 Submission save 方法时会自动生成保存文件的路径。所以我在想,也许我应该在内存中解压缩 zipfile 以获取文件对象数组,然后使用每个文件对象但相同的字段创建一个新的提交,然后让 ActiveRecord 在将它们保存到时为每个文件生成文件路径数据库。 我在这里可能错了,因为我对 Rails 和 Ruby 有点陌生。

【问题讨论】:

    标签: ruby-on-rails ruby file zip


    【解决方案1】:

    我会使用rubyzip gem。具体这部分:https://github.com/rubyzip/rubyzip/blob/master/lib/zip/filesystem.rb

    它在内存中创建一个模拟 zip 文件内容的人工文件系统。这是一个基于文档示例的示例:

    Rubyzip interface changed!!! No need to do require "zip/zip" and Zip prefix in class names removed.

    require 'zip'
    
    Zip::File.open("my.zip") do |zipfile|
      zipfile.each do |file|
        # do something with file
      end
    end
    

    在您的情况下,只需将上传的临时文件的名称放在示例中my.zip 所在的位置,您就可以遍历内容并对其进行常规操作。

    【讨论】:

    • 我明白了,那么如何从 zip 文件中获取文件对象数组?
    • @bizso09,我刚刚更新以展示如何循环浏览内容。这里还有一个简单的教程解释它:markhneedham.com/blog/2008/10/02/…
    • 不幸的是 file 是 ZipEntry 类型而不是 File 类型,所以我无法使用 Submissions 保存它
    • @bizso09,请参阅文档和示例。您可以从 ZipFile 中提取文件,例如 zip_file.extract(f, f_path) unless File.exist?(f_path)
    【解决方案2】:

    来自 RubyZip 项目页面:

    Rubyzip 界面改变了!!!无需移除类名中的“zip/zip”和 Zip 前缀。

    因此,@ben-lee 的示例代码应该更新为如下内容:

    require 'zip'
    
    Zip::File.open("my.zip") do |zipfile|
      zipfile.each do |file|
        # do something with file
      end
    end
    

    【讨论】:

      【解决方案3】:

      在 Ruby 中提取 Zip 文件

      一旦你安装了rubyzip gem,你就可以使用这个方法来解压 zip 文件:

      require 'zip'
      
      def extract_zip(file, destination)
        FileUtils.mkdir_p(destination)
      
        Zip::File.open(file) do |zip_file|
          zip_file.each do |f|
            fpath = File.join(destination, f.name)
            zip_file.extract(f, fpath) unless File.exist?(fpath)
          end
        end
      end
      

      你可以这样使用它:

      extract_zip(zip_path, extract_destination)
      

      【讨论】:

      • 不知道最近有没有改过,但是extract这个方法只需要一个arg,给两个就会报错。
      • 条件unless File.exist?(fpath)背后的原因是什么?这只是为了复制其他工具的行为吗?
      • @JonBurgess 似乎是为了避免用相同的名称替换现有文件。
      【解决方案4】:

      为我工作:

      gem install rubyzip
      

      main.rb

      require 'zip'
      
      def extract_zip(file, destination)
        FileUtils.mkdir_p(destination)
      
        Zip::File.open(file) do |zip_file|
          zip_file.each do |f|
            fpath = File.join(destination, f.name)
            FileUtils.mkdir_p(File.dirname(fpath))
            zip_file.extract(f, fpath) unless File.exist?(fpath)
          end
        end
      end
      
      extract_zip('file.zip', 'tmp')
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-09-12
        • 1970-01-01
        • 2011-10-30
        • 1970-01-01
        相关资源
        最近更新 更多