How to serve images that require authentication.

Hi all,

I have images that are part of a user profile. These images should only be served to other users that view the profile. I'm new to web apps and was wondering what would be the best way to do this in rails. I was considering putting the images in the db and serving them via a controller that would check for authentication and whether the authenticated user can view the image, then send the image. However, I've been reading that this may be inefficient. Any suggestions?

Abhik

I hope this didn't get lost in the sea of spam messages.

One option would be store the images in the file system and store a reference to them in the database. The files should not be accessible via an authenticated URL.

A reasonable way to organize the directory structure if you anticipate many files is to use the current seconds, minutes, etc. in the path such as:

/images/02/37/file_one-02-37.jpg /images/07/21/file_two-07-21.jpg

With a fixed structure like this, you can get by with just storing the file name in the db since the path can be derived from that.

Brian Adkins

Thanks for the tips! What's the disadvantage of storing them in a DB? From what I've read, I'll be pulling the actual binary data from the database, taxing the database and server. Is that the only disadvantage? I'll be initially storing the images on the same server, so would this be any slower than using the filesystem? I'll be using send_file and apparently that loads the entire file into memory which would be no different than using send_data. Thanks!

If you do end up storing the images in the database, keep in mind that rail will, by default, use "SELECT * " when retriving the data for an object. So if you just add a column to your user table that is called profile_picture, you will be loading whatever is in that column into memory when you do something like User.find(1). If you store the image in that column, then you load the image into memory, even if you don't need it. You could update your code to specify the select clause-- User.find(1, :select => 'id, name'), but you would be better off moving the image into it's own table. You could create a model called, ProfilePicture. That model belongs_to :user. User has_one :profile_picture.

There are other reasons for not storing images in a database, but I am probably not the best one to explain the details.

I am using send_file (at http://www.thoughtless.ca) to send images that require authtication. I have had great performance so far. However, my images are very small. Almost all of them are less than 100 kb--most are only about 10-20 kb.

send_file should not need to load the whole file into memory (http:// api.rubyonrails.org/classes/ActionController/Streaming.html#M000228). I haven't tested this myself, but I have generally found that things committed to rails work as advertised.

I hope that helps, Paul

using send_file to serve images will result in huge CPU and memory demands. I suggest using x-send-file and putting the images in the file system.

There's links to the relevant software and articles at http://www.buildingwebapps.com/topic/254-send-files-securely

Michael Slater www.BuildingWebApps.com

Great, thanks for the tips!