Forum: Ruby on Rails file upload

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Tyler C. (Guest)
on 2006-04-17 18:27
This is probably me having an issue with the mvc way of living.. .I'm
used to perl/php scripting...

I've got a photo blog I'm making... and in past iterations of this
website, I'd just name the photos after the id of the entry.  For
instance:

/photos/id.jpg
/photos/id_thumb.jpg

However, I'm having trouble finding an easy way to do this with rails.

Everywhere I read either has an example of how to upload the file
directly into a database, or to use file_column.  While file_column
looks nice and easy, it kind of bugs me that I'd have to create two
columns in my table to support the ability to upload a file...  if I
have to do this, then I will, but I was curious if there is any easy way
to do this.

The only possibility I found was here:
http://wiki.rubyonrails.com/rails/pages/HowtoUploadFiles

However, there were a couple of things I wasn't sure on:
1.  in the view:
<input type="file" name="person[picture]" />

What is [picture] a reference to?  this isn't being stored in the
database... is it just so we can access it with the person class?

2.  The use of file.open... I haven't had much luck finding
documentation on all the options..

File.open("pictures/#{person['name']}/picture.jpg", "w") { |f|
f.write(person['picture'].read) }

I'd really appreciate any help or suggestions.
Thanks
-tyler
Beate P. (Guest)
on 2006-04-17 21:15
(Received via mailing list)
Hi tyler,

I got my fileupload running yesterday for our tumblelog:
http://pkk.kuebelreiter.net/

We wanted to upload files simply to /public/images, without any
database or sth like that.
And I didn't want to associate my images to my Items.

So this is how i managed it:

Created an model image:
class Image
end

(it is emtpy yet, but I wanted to include a method for the override
problem, if a file already exists. But there were some troubles with
that....).

Then I generated a controller image in my admin-directory:


class Admin::ImageController < ApplicationController

  def create
    File.open(RAILS_ROOT +
"/public/images/#{@params['picture'].original_filename}", "w") { |f|
f.write(@params["picture"].read) }
    redirect_to :controller => 'tumble', :action => "new", :bildpfad
=> @request.protocol + @request.host_with_port +
"/images/#{@params['picture'].original_filename}"
  end

  def new
    @image = Image.new
  end

end

And a template under admin/image/new.rthtml:

<%= form_tag({ :action => "create" },  :multipart => true) %>

  <p>Image:
  <input type="file" name="picture" /></p>

  <p><%= submit_tag 'upload' %></p>
<%= end_form_tag %>

Thats all ;)
If you want to rename your files with your post.id, you have to
include the file-logic in your post-controller, to have the post.id.
But I think you get the idea.

You might also look into typo, there is a file-upload for each artikle.

HTH,
Beate
Brez! !. (Guest)
on 2006-04-17 21:19
tyler craft wrote:
> This is probably me having an issue with the mvc way of living.. .I'm
> used to perl/php scripting...

mvc is a design pattern - can be implemented in any language [well
within reason]


> looks nice and easy, it kind of bugs me that I'd have to create two
> columns in my table to support the ability to upload a file...  if I
> have to do this, then I will, but I was curious if there is any easy way
> to do this.

Do you want to store the image on the disk or in a database?

>
> The only possibility I found was here:
> http://wiki.rubyonrails.com/rails/pages/HowtoUploadFiles
>
> However, there were a couple of things I wasn't sure on:
> 1.  in the view:
> <input type="file" name="person[picture]" />
>
> What is [picture] a reference to?  this isn't being stored in the
> database... is it just so we can access it with the person class?

Yes this assumes that there is an object called person [likely an
instnance of ActiveRecord] that has an attribute called picture [which
would most likely be a BLOB in a database somewhere] - to remove the
OOP, you could do this:

<input type="file" name="picture" />

Then access in your controller with: @params['picture']

>
> 2.  The use of file.open... I haven't had much luck finding
> documentation on all the options..

http://corelib.rubyonrails.org/classes/File.html

>
> File.open("pictures/#{person['name']}/picture.jpg", "w") { |f|
> f.write(person['picture'].read) }

the File.new and File.open methods are essentially the same thing
[expect open allows for an included block, i.e the {|f|.. bit] - whats
confusing is that you have to 'open' a file to create it [it actually
makes sense if you got a deep understanding of how file systems work,
but..] - f.write is an input stream for the file, picture.read is an
output stream for the incoming file, i.e. it is read to a write buffer..
this is for writing to a disk btw and not for a database..  clarify
which one youre attempting to do.
Tyler C. (Guest)
on 2006-04-17 22:32
Thanks for the responses.

To clarify, I am simply wanting to save the file to disk, not in a
database.

So, for an example, in my admin/photo view, I'd have this:

<input type="file" name="picture" />

Then, in my admin/photo controller would I then call a function in the
photo model and have this code:

File.open("photos/#{valuePassedIn}.jpg", "w") { |f|
 f.write(@params['picture'].read) }

Thanks again!
-tyler
Steve K. (Guest)
on 2006-04-17 23:09
FileColumn only uses one field, a :string in migrations parlance, i.e.
varchar in typical SQL. In the db it stores the filename of the uploaded
file. If you have that field and

  file_column :field_name

in the model, you're off and running.

tyler craft wrote:
> This is probably me having an issue with the mvc way of living.. .I'm
> used to perl/php scripting...
>
> I've got a photo blog I'm making... and in past iterations of this
> website, I'd just name the photos after the id of the entry.  For
> instance:
>
> /photos/id.jpg
> /photos/id_thumb.jpg
>
> However, I'm having trouble finding an easy way to do this with rails.
>
> Everywhere I read either has an example of how to upload the file
> directly into a database, or to use file_column.  While file_column
> looks nice and easy, it kind of bugs me that I'd have to create two
> columns in my table to support the ability to upload a file...  if I
> have to do this, then I will, but I was curious if there is any easy way
> to do this.
Tyler C. (Guest)
on 2006-04-18 00:04
Steve K. wrote:
> FileColumn only uses one field, a :string in migrations parlance, i.e.
> varchar in typical SQL. In the db it stores the filename of the uploaded
> file. If you have that field and
>
>   file_column :field_name
>
> in the model, you're off and running.
>

But what if I want multiple photos?  For instance, a small/medium/large?
Would I need three extra columns?

...I should be able to have it just name the file off the id and just
through the images into a small/medium/large folder.
Steve K. (Guest)
on 2006-04-18 00:48
If you want multiple versions of the same image, all you do is install
the RMagick gem or ImageMagick on your machine(s) and in your model you
can then say something like

  file_column :field_name, :magick => {:versions =>
    { "thumb" => "80x60", "small" => "150x120", "medium" => "250x200",
      "large" => "640x480" }}

and poof! You have multiple versions of the image all generated, named
and saved automatically. Yes, there's also syntax for constraining one
axis and scaling the other proportaionally. And to display the thumbnail
of, for instance, @photo.image, you'd then simply say

  <%= image_tag url_for_file_column "photo", "image", "thumb" =%>

As for multiple distinct images in the same table row, you simply have a
file_column declaration for each one in the model:

  Class House < ActiveRecord::Base
     file_column :front_view, :magick => {:versions => { "thumb" =>
"80x60" }
     file_column :floorplan
     file_column :kitchen_photo
  end

And of course each of those can have all the resized or manipulated
versions you want.

The file_column docs could use somefleshing out, especially the README.
;)

tyler craft wrote:
> Steve K. wrote:
>> FileColumn only uses one field, a :string in migrations parlance, i.e.
>> varchar in typical SQL. In the db it stores the filename of the uploaded
>> file. If you have that field and
>>
>>   file_column :field_name
>>
>> in the model, you're off and running.
>>
>
> But what if I want multiple photos?  For instance, a small/medium/large?
> Would I need three extra columns?
>
> ...I should be able to have it just name the file off the id and just
> through the images into a small/medium/large folder.
Surekha M. (Guest)
on 2006-05-02 16:43
Beate P. wrote:
> Hi tyler,
>
> I got my fileupload running yesterday for our tumblelog:
> http://pkk.kuebelreiter.net/
>
> We wanted to upload files simply to /public/images, without any
> database or sth like that.
> And I didn't want to associate my images to my Items.
>
> So this is how i managed it:
>
> Created an model image:
> class Image
> end
>
> (it is emtpy yet, but I wanted to include a method for the override
> problem, if a file already exists. But there were some troubles with
> that....).
>
> Then I generated a controller image in my admin-directory:
>
>
> class Admin::ImageController < ApplicationController
>
>   def create
>     File.open(RAILS_ROOT +
> "/public/images/#{@params['picture'].original_filename}", "w") { |f|
> f.write(@params["picture"].read) }
>     redirect_to :controller => 'tumble', :action => "new", :bildpfad
> => @request.protocol + @request.host_with_port +
> "/images/#{@params['picture'].original_filename}"
>   end
>
>   def new
>     @image = Image.new
>   end
>
> end
>
> And a template under admin/image/new.rthtml:
>
> <%= form_tag({ :action => "create" },  :multipart => true) %>
>
>   <p>Image:
>   <input type="file" name="picture" /></p>
>
>   <p><%= submit_tag 'upload' %></p>
> <%= end_form_tag %>
>
> Thats all ;)
> If you want to rename your files with your post.id, you have to
> include the file-logic in your post-controller, to have the post.id.
> But I think you get the idea.
>
> You might also look into typo, there is a file-upload for each artikle.
>
> HTH,
> Beate

I used this code, after runs this programme the images are uploaded into
the images folder, but If iam trying to open uploaded images, those are
opened but overlapped (I mean to say that not as the original image)
with some other images. So plz help me out in uploading as the original
image.

        and another thing is, I used this file tag in a form, after
submit in the controller, it displayes an error as original_filename
undefined method.
what I have to do.

Thanks in advance
Surekha.Matte
tyler (Guest)
on 2006-05-02 16:56
this is the code I ended up using.  I have a form that has an image
submit button on it, and when i update it, I run this code:

if @photo.update_attributes(params[:photo])
    		if @params["thumbnail"].size != 0
    			File.open("#{RAILS_ROOT}/public/photos/#{@photo.id}_thumb.jpg",
"wb") { |f| f.write(@params["thumbnail"].read) }
    		end
end
This topic is locked and can not be replied to.