File uploading techniques

Hi Everyone,
I need to upload a file (its a picture) to the database. In php, i
can do it by 2 ways:-
1.) directly upload the picture to the database (‘blob’ column)
2.) upload the file to a directory created by us and put the reference
to that directory in the database. then put that “reference url” in
image tag to display.
I prefer the “2” option. How can i do this in Ruby on Rails??
My database name “contents” & column name “picture” -> what should be
the column type??

I used the following code to bring file open dialog,
<%= file_field ‘content’, ‘picture’ %>
when i select a picture file and click “add” or “update” button,
something gets stored in database. At present i have set the column type
for “picture” column as “blob”. But i dont know what it is and how to
display it.

Please anyone help me…

PS: Also tell me which is the best way to upload a picture file (out of
the 2 i mentioned above). If there is anyother method, please tell me…

Thanks in advance
Regards,
Vasanth

Vasanthakumar C. wrote:

Hi Everyone,
I need to upload a file (its a picture) to the database. In php, i
can do it by 2 ways:-
1.) directly upload the picture to the database (‘blob’ column)
2.) upload the file to a directory created by us and put the reference
to that directory in the database. then put that “reference url” in
image tag to display.
I prefer the “2” option. How can i do this in Ruby on Rails??
My database name “contents” & column name “picture” → what should be
the column type??

Make sure to look into the FlexImage plugin:
http://www.agilewebdevelopment.com/plugins/fleximage

It handles a lot fo the uploading and disk or database writing for you.

However, if you still want to do it yourself:

To store data in DB:

#controller
def update
@content = Content.find(params[:id])
if params[:content][:picture] && params[:content][:picture].size > 0
@content.data = params[:content][:picture].read
end
@content.save
end

def image
data = Content.find(params[:id]).data
send_data data, :disposition => ‘inline’
end

#view

Or on the disk:

def update
@content = Content.find(params[:id])
if params[:content][:picture] && params[:content][:picture].size > 0
File.open(“#{RAILS_ROOT}/images/foo/#{@coontent.id}” do |f|
f.write params[:content][:picture].read
end
end
@content.save
end

def image
send_file “#{RAILS_ROOT}/images/foo/#{params[:id]}”,
:disposition => ‘inline’
end

In either case you can display the image by going to that action, or
linking to it form an image tag:

<%= image_tag url_for(:action => ‘image’, :id => 1) %>

But really check out flex image. It makes this much easier and
flexible.

Vasanthakumar C. wrote:

Hi,
I did what all u said (uploading file to database & also directory)
but nothing worked out.

Error messages can be helpful…

Dont know where i am going wrong. Please check
this code below:-
I wrote it to upload a file to database:-

This code here writes it to filesystem not the database.

def update
@content = Content.find_by_id(params[:id])
@content.updatedBy = session[:user_id]
@content.updatedOn = Time.now

Just a little tip: if you have a column called updated_on or updated_at
rails will automatically set its values. Same is true for created_on /
created_at.

if params[:content][:picture] && params[:content][:picture].size > 0

We only want to upload a file if one exists in the parameters. This
checks that the param we want exists and make sures that it actually has
data in it (".size > 0" meaning they uploaded a file instead of just
left the file field blank)

  File.open("#{RAILS_ROOT}/images/#{params[:content][:picture]}", 
            'wb+') do |f|

Since we are writing a file, we need to open it first. The first
argument is the path on your web server to the file. Make sure to start
it with the RAILS_ROOT constant to ensure that you are writing file with
paths relative to your home directory. This path would yield something
like:

/home/my_rails_app/images/123

The second argument is the file mode, in this case ‘wb+’ broken into its
parts means:

‘w’ : open file for writing
‘b’ : in binary mode
‘+’ : create file if it doesnt it.

    f.write params[:content][:picture].read

Now that we are inside the open file block we can write to the file
itself with file.write. You can get the uploaded file data as a string
with the read method. So we write the file to disk by reading the
uploaded file.

  end
end
@content.save

end

def image
send_file “#{RAILS_ROOT}/images/#{params[:id]}”, :disposition =>
‘inline’
end

I just blindly put the code u gave… dont know what it does. whats the
method “def image” for?? it is not called anywhere - is it automatically
called??

“image” is an action in the controller that is called just like any
other action. Except instead returning HTML, it returns binary data.
send_file will make rails open a file anywhere on your web server and
then send its contents in response to the request. So use it your view
to place these images.

<%= image_tag(:action => ‘image’, :id => 123) %>

Alternatively, you can upload the file to your public directory, in
which case you don’t need to have an image action at all, just link to
the the publicly accessible file.

<%= image_tag(’/images/123.jpg’) %>

Please help me out…

I hope that I just did. And I once again recommend using flex image as
this sort of thing can be kind of a pain. With a FlexImage::Model class
you can simply assign the binary upload the same as you would any other
column. Assuming you have uploaded a file into params[:content][:data]
and any other attributes in the params[:content] hash

Content is a FlexImage::Model class

Content.create(params[:content])

So you dont have to write any code that treats the binary column
different that the other data in your model.

I also want to point out a minor caveat. You must use “:multipart =>
true” on your form_tag. Otherwise no binary data will be sent with your
form submission.

<%= form_tag({:action => ‘upload_file’}, {:multipart => true}) %>

Good luck,
-Alex

Hi,
I did what all u said (uploading file to database & also directory)
but nothing worked out. Dont know where i am going wrong. Please check
this code below:-
I wrote it to upload a file to database:-

def update
@content = Content.find_by_id(params[:id])
@content.updatedBy = session[:user_id]
@content.updatedOn = Time.now

if params[:content][:picture] && params[:content][:picture].size > 0
  File.open(params[:content][:picture]) do |f|
    f.write params[:content][:picture].read
  end
end
@content.save
send_file "#{RAILS_ROOT}/images/#{params[:id]}", :disposition => 

‘inline’

if @content.update_attributes(params[:content])
  redirect_to :action => 'index'
else
  render :action => 'edit'
end

end

def image
send_file “#{RAILS_ROOT}/images/#{params[:id]}”, :disposition =>
‘inline’
end

I just blindly put the code u gave… dont know what it does. whats the
method “def image” for?? it is not called anywhere - is it automatically
called??

Please help me out…

Thanks in advance
Regards,
Vasanth

Alex W. wrote:

<%= image_tag(:action => ‘image’, :id => 123) %>

My bad, that should be:

<%= image_tag(url_for(:action => ‘image’, :id => 123)) %>

Bala P. wrote:

Is FlexImage better than file_column?

I am biased because it’s my plugin. But it certainly is cool. Pull
images from DB or disk at any size you want, optionally add order
borders, text, drop shadows or overlays.

File column cant so that.

Is FlexImage better than file_column?

Use acts_as_attachment

-Pratik

On 12/9/06, Vasanthakumar C. [email protected] wrote:

the column type??
PS: Also tell me which is the best way to upload a picture file (out of


rm -rf / 2>/dev/null - http://null.in

Dont judge those who try and fail, judge those who fail to try…

Hi Alex W.,
Thanks a lot for ur help, as it was weekend i couldn’t reply. It
was nice to see u give a detailed explanation. Now i understood the
flow.
But the problem is not solved yet… here is the code and the
error

Code:-
File.open("#{RAILS_ROOT}/images/#{params[:id]}", ‘wb+’) do |f|
f.write params[:content][:picture].read
end

Error:-
Errno::ENOENT in ContentController#update
No such file or directory - ./images/1

Request Parameters: {“multipart”=>“true”, “commit”=>“Update”, “id”=>“1”,
“content”=>{“title”=>“Test 1”, “startDt(1i)”=>“2006”,
“startDt(2i)”=>“12”, “description”=>“Test Description 1 a”,
“startDt(3i)”=>“3”, “picture”=>“C:\Documents and Settings\kalyava\My
Documents\My Pictures\Beautiful Quotations\CA03SREF.jpg”}}

Think the file couldn’t be created. I search in google but couldn’t get
any proper solution. Can anyone guide me?? Am stuck up with this for
almost 4 days now… :frowning:

Thanks in advance
Regards,
Vasanth

Vasanthakumar C. wrote:

Code:-
File.open("#{RAILS_ROOT}/images/#{params[:id]}", ‘wb+’) do |f|
f.write params[:content][:picture].read
end

Error:-
Errno::ENOENT in ContentController#update
No such file or directory - ./images/1

Look in your application root. Is there a directory called images? The
directory needs to exist before you open a file inside of it. So either
create “#{RAILS_ROOT}/images” or change the location in File.open to a
folder that actually exists.