In my previous article on using ImageMagick and Mini-Magick to manipulate images in Ruby on Rails, I talked about how to install all of the goodies you’d need to work with images in Rails. I thought I’d expand on this a little bit more and give an example on how I used this cool stuff to upload images and resize them in my Rails application.
You’ll need to set up some HTML code to upload the file to the server. Something like this will suffice:
<% form_tag :action => 'upload', :multipart => true, :id => 'upload_form' do -%> <input style="margin-left: 5px;" type="file" id="imageone_file" name="imageone[file]" /> <% end -%>
Now you’ll want to build a model (based on ActiveRecord or not) to save your image for you. For my use, I did based my image model on an ActiveRecord class since I wanted to at least store the file name of the image in my database. But doing that is up to you. Anyway, on to saving the image. In your class, you want to grab the data for the image file in the posted form and save it to the file system. Something like this will suffice:
def image_save(file) @file = file @content_type = file.content_type.chomp @original_filename = base_part_of(file.original_filename) @extension = @original_filename[@original_filename.rindex(".") .. @original_filename.length].strip.chomp self.file_name = "#{epoch_time()}#{@extension}" is_saved = false begin if self.file if self.content_type =~ /^image/ # Make the directory for the id of the listing if it doesn't exist Dir.mkdir("#{RAILS_ROOT}/public/images/originals/") unless File.exists?("#{RAILS_ROOT}/public/images/originals/") # What's the new file name? # Create the temporary file File.open("#{RAILS_ROOT}/public/images/originals/#{self.file_name}", "wb") do |f| f.write(@file.read) f.close end # Crop the image to the sizes we need crop() is_saved = true end end rescue end return is_saved end
So what are we doing here? First, we grab the content type of the file, its original file name, and the extension of the file. We save this information out to attributes defined on the model itself, i.e.
attr_accessor :file, :content_type, :original_filename, :extension
Then we check to make sure the directory where we want to save the original file exists, and if not, create it. Then we save the file itself. Once we have the file saved, you’ll notice I call a method called crop(). This is my method that resizes the original image and saves the resized images to the file system. How do I do that? Check this out:
def crop() image = MiniMagick::Image.from_file("#{RAILS_ROOT}/public/images/originals/#{self.file_name}") if !image.nil? # Resize to 360x360 image.resize "360x360" image.write("#{RAILS_ROOT}/public/images/360x360/#{self.file_name}") # Resize to 240x240 image.resize "240x240" image.write("#{RAILS_ROOT}/public/images/240x240/#{self.file_name}") # Resize to 120x120 image.resize "120x120" image.write("#{RAILS_ROOT}/public/images/120x120/#{self.file_name}") # Resize to 80x80 image.resize "80x80" image.write("#{RAILS_ROOT}/public/images/80x80/#{self.file_name}") # Resize to 40x40 image.resize "40x40" image.write("#{RAILS_ROOT}/public/images/40x40/#{self.file_name}") end end
As you can tell, I needed several different image sizes. You start with the lowest size and work your way down. Not doing this gets you funky sized images. MiniMagick makes it really easy to just open the file and set the new size for the image and then just write it out to where you want it. Nice!