6

我目前正在尝试将图像文件直接从 zip 文件附加到模型(即,无需先将它们保存在磁盘上)。似乎应该有一种更清晰的方法将 ZipEntry 转换为可以存储在内存中的 Tempfile 或 File 以传递给另一个知道如何处理它的方法或对象。

这是我的代码:

def extract (file = nil)
  Zip::ZipFile.open(file) { |zip_file|
    zip_file.each { |image|
      photo = self.photos.build
      # photo.image = image # this doesn't work
      # photo.image = File.open image # also doesn't work
      # photo.image = File.new image.filename
      photo.save
    }
  }
end

但问题是 photo.image 是模型的附件(通过回形针),并且将某些内容分配为附件需要某些内容是 File 对象。但是,我一生都无法弄清楚如何将 ZipEntry 转换为文件。我见过的打开或创建文件的唯一方法是在其路径中使用一个字符串——这意味着我必须将文件提取到一个位置。真的,这似乎很愚蠢。为什么我不能将 ZipEntry 文件提取到输出流并将其转换为那里的文件?

所以最终的问题是:我可以从 Zip 文件中提取 ZipEntry 并将其直接转换为 File 对象(或将其直接附加为 Paperclip 对象)吗?还是我在附加它之前实际上将它存储在硬盘上,即使该版本最终会被删除?

更新 感谢蓝莓领域,我想我离我的解决方案更近了一点。这是我添加的代码行,它为我提供了我需要的 Tempfile/File:

photo.image = zip_file.get_output_stream image

但是,我的Photo对象不会接受通过的文件,因为它不是image/jpeg. 事实上,检查content_type文件显示application/x-empty. 我认为这可能是因为获取输出流似乎在文件末尾附加了一个时间戳,因此它最终看起来像imagename.jpg20110203-20203-hukq0n. 编辑:此外,它创建的临时文件不包含任何数据,大小为 0。所以看起来这可能不是答案。

那么,下一个问题:有谁知道如何得到这个给我一个图像/jpeg 文件?

更新

我一直在玩这个。似乎输出流不是要走的路,而是输入流(这总是让我感到困惑)。在 ZipEntry 上使用 get_input_stream,我得到了文件中的二进制数据。我想现在我只需要弄清楚如何将它放入回形针附件(作为文件对象)。我尝试将 ZipInputStream 直接推送到附件,但当然,这不起作用。我真的很难相信没有人尝试将提取的 ZipEntry 转换为文件。有什么理由认为这会被认为是不好的编程习惯吗?在我看来,跳过临时文件的磁盘写入是完全可以接受的,并且在 Zip 存档管理之类的东西中得到支持。

无论如何,问题仍然存在:

有没有办法将输入流转换为文件对象(或临时文件)?最好不必写入磁盘。

4

2 回答 2

6

尝试这个

Zip::ZipFile.open(params[:avatar].path) do |zipfile|
  zipfile.each do |entry|
    filename = entry.name
    basename = File.basename(filename)

    tempfile = Tempfile.new(basename)
    tempfile.binmode
    tempfile.write entry.get_input_stream.read

    user = User.new
    user.avatar = {
      :tempfile => tempfile,
      :filename => filename
    }
    user.save

  end
end
于 2011-08-05T11:15:52.927 回答
0

Check out the get_input_stream and get_output_stream messages on ZipFile.

于 2011-02-04T00:39:46.957 回答