How to get a temporary File object (the correct type of content, without writing to disk) directly from ZipEntry (RubyZip, Paperclip, Rails 3)?

I am currently trying to connect image files to a model directly from a zip file (i.e. without saving them to disk). There seems to be a clearer way to convert ZipEntry to Tempfile or a file that can be stored in memory for transfer to another method or object that knows what to do with it.

Here is my code:

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 

But the problem is that photo.image is an attachment (via paperclip) to the model, and assigning something as an attachment requires that something be a File object. However, I cannot understand my whole life how to convert ZipEntry to a file. The only way I saw opening or creating a File is to use a string for its path - this means that I have to extract the file to a location. This is actually just stupid. Why can't I just extract the ZipEntry file into an output stream and convert it to a file there?

So the final question is: can I extract a ZipEntry from a Zip file and transfer it directly to a File object (or directly link it as a Paperclip object)? Or am I actually stuck storing it on my hard drive before I can plug it in, although this version will be removed at the end?

UPDATE Thanks to the bluish fields, I think I'm a little closer to my decision. Here is 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 

However, my Photo object will not accept the transferred file, since it is not image/jpeg . In fact, checking the content_type file shows application/x-empty . I think this may be due to the fact that getting the output stream seems to add a timestamp to the end of the file, so it looks like imagename.jpg20110203-20203-hukq0n . Change Also, the temp file you create does not contain any data and has a size of 0. So this seems like it, this may not be the answer.

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

UPDATE :

I played with this a little more. It seems that the output stream is not a path, but an input stream (which has always confused me). Using get_input_stream in ZipEntry, I get binary data in a file. I think now I just need to figure out how to do this in a Paperclip application (as a File object). I tried to push ZipInputStream directly on the attachment, but of course this does not work. It’s really hard for me to believe that no one tried to take the extracted ZipEntry as a file. Is there any reason this would be considered bad programming practice? It seems to me that skipping a write to disk for a temporary file would be quite acceptable and supported in something like managing Zip archives.

Anyway, the question still stands:

Is there a way to convert the input stream to a File (or Tempfile) object? Preferably without the need to write to disk.

+6
file inputstream ruby-on-rails-3 paperclip rubyzip
source share
2 answers

try it

 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 
+6
source share

Check the get_input_stream and get_output_stream messages on the ZipFile.

+1
source share

All Articles