From: Joe Van Dyk Date: 2005-08-04T11:30:14+09:00 Subject: Re: RMagick problem On 8/3/05, Joe Van Dyk wrote: > On 8/3/05, Tim Hunter wrote: > > Joe Van Dyk wrote: > > > > > The following Rails/Ruby code gives me this error: "Zero-length blob > > > not permitted". > > > > > > @magick_image = Magick::Image.from_blob(@file.read).first > > > > > > Where @file is a StringIO object or a File object, depending on the > > > size of the uploaded file. > > > > > > @file.read.size returns the expected file size (in bytes). > > > > > > Any ideas? > > > > Well, it works for me. Here's my attempt to reproduce the problem. > > > > require 'RMagick' > > require 'stringio' > > > > file = File.open('Flower_Hat.jpg') > > img = Magick::Image.from_blob(file.read).first > > p img > > > > blob = IO.read('Flower_Hat.jpg') > > sio = StringIO.new(blob) > > img = Magick::Image.from_blob(sio.read).first > > p img > > > > > > The output is: > > tim: ~> ruby test.rb > > JPEG 200x250 DirectClass 8-bit 9kb > > JPEG 200x250 DirectClass 8-bit 9kb > > Yeah, I tried to do that test last night and it worked fine. > > So I have no idea why the code is failing inside my Image model. Here's my image model. Perhaps that will give someone some insight. Say, I'm doing the Magick::Image.from_blob call in #after_save. Perhaps something weird is happening with @file's lifetime or something? class Image < ActiveRecord::Base belongs_to :house belongs_to :community belongs_to :contractor FileLocation = "#{RAILS_ROOT}/public/media/" DisplayLocation = "/media" def file=(file) if file.size > 0 self.content_type = file.content_type.strip @file = file end end # Runs after Image is saved, saves the image to the file system. def after_save if @file @magick_image = Magick::Image.from_blob(@file.read).first save_full_image save_thumbnail_image save_rounded_thumbnail_image save_medium_image save_large_image end end # If image is already a jpeg, then just write it to a file. # If it's not, convert it to a jpeg and then write. def save_full_image @magick_image.write(full_file) end # Write a thumbnail to the filesystem def save_thumbnail_image thumbnailed_magick_image = resize_image_to_exact_size(180,135) thumbnailed_magick_image.write(thumbnail_file) end def save_rounded_thumbnail_image thumbnail_image = resize_image_to_exact_size(180, 135) color = "#000033" corner_width = 15 corners = Magick::Draw.new corners.stroke(color) corners.fill_opacity(0) corners.stroke_width(15) corners.roundrectangle(0, 0, thumbnail_image.columns, thumbnail_image.rows, corner_width, corner_width) corners.draw(thumbnail_image) thumbnail_image.write(rounded_thumbnail_file) end # Resizes a Magick image to an exact size, keeping the same aspect ratio def resize_image_to_exact_size(width, height) new_aspect_ratio = width.to_f / height.to_f old_aspect_ratio = @magick_image.columns.to_f / @magick_image.rows.to_f if old_aspect_ratio < new_aspect_ratio # Image too tall, geometry string should restrict height geometry_string = "#{width}" else # Image too wide or just right, geometry string should # restrict width geometry_string = "x#{height}" end # Get the resized image resized_image = resize_image(geometry_string) # Return the resized, crop image resized_image.crop(Magick::CenterGravity, width, height) end def resize_image(geometry_string) logger.debug "resizing image to #{geometry_string}" @magick_image.change_geometry(geometry_string) do |w, h, img| img.resize(w, h) end end def save_medium_image medium_image = resize_image("275") medium_image.write(medium_file) end def save_large_image large_image = resize_image("500") large_image.write(large_file) end # Delete images from filesystem def after_destroy File.delete(full_file) if File.exist? "#{full_file}" File.delete(thumbnail_file) if File.exist? "#{thumbnail_file}" File.delete(rounded_thumbnail_file) if File.exist? "#{rounded_thumbnail_file}" File.delete(medium_file) if File.exist? "#{medium_file}" File.delete(large_file) if File.exist? "#{large_file}" end # Returns the filesystem location of the image file def full_file "#{FileLocation}/full/#{id}.jpg" end def thumbnail_file "#{FileLocation}/thumbnail/#{id}.jpg" end def rounded_thumbnail_file "#{FileLocation}/rounded_thumbnail/#{id}.jpg" end def medium_file "#{FileLocation}/medium/#{id}.jpg" end def large_file "#{FileLocation}/large/#{id}.jpg" end # Returns the location of the image to the browser def full "#{DisplayLocation}/full/#{id}.jpg" end def thumbnail "#{DisplayLocation}/thumbnail/#{id}.jpg" end def medium "#{DisplayLocation}/medium/#{id}.jpg" end def large "#{DisplayLocation}/large/#{id}.jpg" end def rounded_thumbnail "#{DisplayLocation}/rounded_thumbnail/#{id}.jpg" end def resize if File.exist? full_file @file = File.open full_file save end end end