如何直接从ZipEntry(RubyZip,Paperclip,Rails 3)获得临时File对象(具有正确的内容类型,而无需写入磁盘)? [英] How do I get a temporary File object (of correct content-type, without writing to disk) directly from a ZipEntry (RubyZip, Paperclip, Rails 3)?

查看:195
本文介绍了如何直接从ZipEntry(RubyZip,Paperclip,Rails 3)获得临时File对象(具有正确的内容类型,而无需写入磁盘)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm currently trying to attach image files to a model directly from a zip file (i.e. without first saving them on a disk). It seems like there should be a clearer way of converting a ZipEntry to a Tempfile or File that can be stored in memory to be passed to another method or object that knows what to do with it.

这是我的代码:

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文件提取到输出流中并在那里将其转换为File?

But the problem is that photo.image is an attachment (via paperclip) to the model, and assigning something as an attachment requires that something to be a File object. However, I cannot for the life of me figure out how to convert a ZipEntry to a File. The only way I've seen of opening or creating a File is to use a string to its path - meaning I have to extract the file to a location. Really, that just seems silly. Why can't I just extract the ZipEntry file to the output stream and convert it to a File there?

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

So the ultimate question: Can I extract a ZipEntry from a Zip file and turn it directly into a File object (or attach it directly as a Paperclip object)? Or am I stuck actually storing it on the hard drive before I can attach it, even though that version will be deleted in the end?

更新 多亏了蓝莓田,我想我离解决方案有点近了.这是我添加的代码行,它为我提供了所需的临时文件/文件:

UPDATE Thanks to blueberry fields, I think I'm a little closer to my solution. Here's the line of code that I added, and it gives me the Tempfile/File that I need:

photo.image = zip_file.get_output_stream image

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

However, my Photo object won't accept the file that's getting passed, since it's not an image/jpeg. In fact, checking the content_type of the file shows application/x-empty. I think this may be because getting the output stream seems to append a timestamp to the end of the file, so that it ends up looking like imagename.jpg20110203-20203-hukq0n. Edit: Also, the tempfile that it creates doesn't contain any data and is of size 0. So it's looking like this might not be the answer.

那么,下一个问题:有谁知道如何获取这个图像/jpeg文件?

So, next question: does anyone know how to get this to give me an image/jpeg file?

更新:

我一直在玩这个游戏.似乎输出流不是要走的路,而是输入流(这总是让我感到困惑).使用ZipEntry上的get_input_stream,可以在文件中获取二进制数据.我想现在我只需要弄清楚如何将其放入Paperclip附件(作为File对象)即可.我尝试将ZipInputStream直接推到附件,但是那当然行不通.我真的很难相信,没有人试图将提取的ZipEntry转换为文件.是否出于某种原因将其视为不良的编程习惯?在我看来,跳过临时文件的磁盘写入是完全可以接受的,并且在诸如Zip存档管理之类的方法中受支持.

I've been playing around with this some more. It seems output stream is not the way to go, but rather an input stream (which is which has always kind of confused me). Using get_input_stream on the ZipEntry, I get the binary data in the file. I think now I just need to figure out how to get this into a Paperclip attachment (as a File object). I've tried pushing the ZipInputStream directly to the attachment, but of course, that doesn't work. I really find it hard to believe that no one has tried to cast an extracted ZipEntry as a File. Is there some reason that this would be considered bad programming practice? It seems to me like skipping the disk write for a temp file would be perfectly acceptable and supported in something like Zip archive management.

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

Anyway, the question still stands:

是否可以将输入流转换为File对象(或Tempfile)?最好不必写入磁盘.

Is there a way of converting an Input Stream to a File object (or Tempfile)? Preferably without having to write to a disk.

推荐答案

尝试一下

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

这篇关于如何直接从ZipEntry(RubyZip,Paperclip,Rails 3)获得临时File对象(具有正确的内容类型,而无需写入磁盘)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆