我目前正在尝试直接从 zip 文件将图像文件附加到模型(即不先将它们保存在磁盘上)。似乎应该有一种更清晰的方法将 ZipEntry 转换为可以存储在内存中的临时文件或文件,以便传递给知道如何处理它的另一个方法或对象。
这是我的代码:
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 对象)吗?还是我在附加它之前实际上将其存储在硬盘驱动器上,即使该版本最终会被删除?
UPDATE感谢蓝莓田,我想我离我的解决方案更近了一些。这是我添加的代码行,它为我提供了我需要的临时文件/文件:
photo.image = zip_file.get_output_stream image
然而,我的Photo
对象不会接受正在传递的文件,因为它不是image/jpeg
。事实上,检查content_type
该文件显示application/x-empty
。我认为这可能是因为获取输出流似乎会在文件末尾附加一个时间戳,因此它最终看起来像imagename.jpg20110203-20203-hukq0n
. Edit:此外,它创建的临时文件不包含任何数据,大小为 0。所以看起来这可能不是答案。
那么,下一个问题:有谁知道如何得到它来给我一个图像/jpeg 文件?
UPDATE:
我一直在玩这个。看来输出流不是要走的路,而是输入流(这总是让我感到困惑)。在 ZipEntry 上使用 get_input_stream,我获取文件中的二进制数据。我想现在我只需要弄清楚如何将其放入回形针附件(作为文件对象)。我尝试过将 ZipInputStream 直接推送到附件,但是当然,这是行不通的。我真的很难相信没有人尝试将提取的 ZipEntry 转换为文件。是否有某种原因认为这会被认为是不好的编程实践?在我看来,跳过临时文件的磁盘写入是完全可以接受的,并且在 Zip 存档管理之类的东西中受到支持。
无论如何,问题仍然存在:
有没有办法将输入流转换为文件对象(或临时文件)?最好不必写入磁盘。