# Picture uploading / validating / resizing

**URL:** <https://www.ruby-forum.com/t/picture-uploading-validating-resizing/49220>\
**Category:** Rails\
**Created:** [December 1, 2005, 4:05pm UTC](https://www.ruby-forum.com/t/picture-uploading-validating-resizing/49220 "2005-12-01T16:05:53Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![msojka](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/b5a626/32.png) [@msojka](https://www.ruby-forum.com/u/msojka)\
**Post date:** [December 1, 2005, 4:05pm UTC](https://www.ruby-forum.com/t/picture-uploading-validating-resizing/49220/1 "2005-12-01T16:05:53Z")

</div>

Hello,

I’m researching various options to handle picture  
uploading/validating/resizing in Rails.

I plan to have one table “pictures” (model Picture) which will store all  
pictures. These pictures can then be assigned to other models through  
associations.

Here is the process:

1. User browses the picture and uploads it.
2. Picture’s content-type and size are validated (e.g. max 1MB size)
3. Picture is autmatically resized to a given size (e.g. 700x500) and  
converted to JPG. This resulting JPG is stored in the file system as  
“original”. The path pointing to the picture should be  
“/public/pictures/\<picture.id\>/original.jpg”. Temp folder should be used  
for form redisplays in some situations.
4. Views can request original jpg or some modified version (using  
rmagick modifications) - e.g. view can request 200x100 version of the  
original. These modified versions are cached in the file system.

I’ve started to play with file\_column and ImageMagick for Rails.

Can this scenario be accomplished using these 2 extensions? Or do you  
know about some other helpful resources?

Thanks for any help 😉

---

<div class="post-metadata">

**Author:** ![msojka](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/b5a626/32.png) [@msojka](https://www.ruby-forum.com/u/msojka)\
**Post date:** [December 1, 2005, 6:15pm UTC](https://www.ruby-forum.com/t/picture-uploading-validating-resizing/49220/2 "2005-12-01T18:15:21Z")

</div>

I’m doing something very similar (I do thumbnailing for images that  
represent users), but I’m not using file\_column, I’m just using a BLOB  
column. I haven’t done any scale testing yet, so I might have to switch  
to  
some file caching scheme in the future.

I made some small additions to the Picture class from the Agile book.  
Here’s the code:

#—

# Excerpted from “Agile Web D. with Rails”

# We make no guarantees that this code is fit for any purpose.

# Visit [http://www.pragmaticprogrammer.com](http://www.pragmaticprogrammer.com) for more book information.

#—  
class Picture \< ActiveRecord::Base

validates\_format\_of :content\_type, :with =\> /^image/,  
:message =\> “— you can only upload pictures”

#MES- TODO: We may want to delay loading the data column- loading the  
data

# just to get info like the extension might get expensive.

DEFAULT\_THUMBNAIL\_HEIGHT = 50.0

MAX\_IMAGE\_SIZE = 1 \* 1024 \* 1024

def picture=(picture\_field)  
self.name = base\_part\_of(picture\_field.original\_filename)  
self.extension = File.extname(self.name)  
self.content\_type = picture\_field.content\_type.chomp  
self.data = picture\_field.read  
end

def check\_valid  
#MES- Check that the data isn’t too big  
if MAX\_IMAGE\_SIZE \< data.length  
raise “Image too large”  
end

```
#MES- Check that the blob we contain is an image
return false if !load_image_lib
begin
  img = Magick::Image.from_blob(data)
  return true
rescue
  #MES- If we get an exception converting it to an image, then it's 

```

not  
good  
raise “Image format not recognized”  
end

end

def base\_part\_of(file\_name)  
name = File.basename(file\_name)  
name.gsub(/[^\w.\_-]/, ‘’)  
end

def create\_thumbnail(height = DEFAULT\_THUMBNAIL\_HEIGHT)  
#MES- Only do thumbnailing if the Image Magick library can be  
loaded.  
# This is to make setup easier for other developers- they are not  
# required to have Image Magick.  
# More information on Image Magick is available at  
# [http://studio.imagemagick.org/RMagick/doc/usage.html](http://studio.imagemagick.org/RMagick/doc/usage.html)  
if load\_image\_lib  
#MES- Turn the blob into an ImageMagick object  
img = Magick::Image.from\_blob(data).first  
if img.nil?  
logger.info “Failed to make thumbnail for image #{self.name}-  
unable  
to create RMagick wrapper for image”  
return nil  
end  
#MES- Shrink the image  
thumbnail = img.thumbnail(height/img.rows.to\_f)  
#MES- Store it into a new Picture object and return it  
return Picture.create(:name =\> self.name, :extension =\>  
self.extension,  
:content\_type =\> self.content\_type, :data =\> thumbnail.to\_blob)  
else  
return nil  
end  
end

def load\_image\_lib  
begin  
#MES- Note that “require” caches values, so calling it multiple  
times  
should NOT cause the  
# library to be loaded multiple times.  
require ‘RMagick’  
return true  
rescue MissingSourceFile  
logger.info ‘In Picture::load\_image\_lib. The RMagick library  
could  
not be loaded, so image manipulations will not be performed.’  
return false  
end  
end  
end

and here’s the schema I’m using:

CREATE TABLE `pictures` (  
`id` \<%= @pk %\>,  
`name` varchar(255) default NULL,  
`extension` varchar(255) default NULL,  
`content_type` varchar(255) default NULL,  
`data` blob,  
`created_at` \<%= @datetime %\>,  
`updated_at` \<%= @datetime %\>  
) \<%= @options %\>;

To display the image, I put methods into my controller, like this:

def image  
@user = User.find(params[:id])  
send\_image(@user.image)  
end

def thumbnail  
@user = User.find(params[:id])  
send\_image(@user.thumbnail)  
end

def send\_image(img)  
send\_data(img.data, :filename =\> img.name, :type =\>  
img.content\_type,  
:disposition =\> ‘inline’)  
end

and I generate URLs like this:

def build\_user\_thumbnail\_url(user)  
if !user.thumbnail.nil?  
return image\_tag(url\_for(:controller =\> ‘user’, :action =\>  
‘thumbnail’, :id =\> “#{user.id}#{user.thumbnail.extension}”))  
else  
return “ ![](https://www.ruby-forum.com/images/noimage.jpg)”  
end  
end

Finally, I add to my routes.rb to handle various image extensions:

#MES- Map any file extension for user ‘image’ or ‘thumbnail’ to the  
action  
map.connect ‘user/image/:id’, :controller =\> ‘user’, :action =\>  
‘image’,  
:id =\> /^._.._$/  
map.connect ‘user/thumbnail/:id’, :controller =\> ‘user’, :action =\>  
‘thumbnail’, :id =\> /^._.._$/

I hope that helps
