kaplan
kaplan

Reputation: 4229

basic file upload in rails with form helper

I'm trying to get my head around the basic file upload with the form helper in Rails using the edge rails guide (I'm using rails 4.0.0.rc1 and ruby 1.9.3p362) before I get into Paperclip or CarrierWave.

I put the method for the upload right in with my #create in the Controller, my plan was to create the new record with an :image column that stored the filename of my upload.

My #create has this:

File.open(Rails.root.join('public', 'uploads', uploaded_io.original_filename), 'w') do |file|
  file.write(uploaded_io.read)
end

When I follow the Rails Guide exactly the file upload happens, I can see the file in my public/uploads, but I get an encoding error in the browser:
Encoding::UndefinedConversionError
"\x89" from ASCII-8BIT to UTF-8

The \x89 is the dot on the suffix of the filename? ie: .png

I found a StackOverflow post that said to add the 'b' to the File.open, that fixes the Encoding error, but I get a different error. This StackOverflow post covers my error, but I believe I'm following the solution and still have the error.

File.open(Rails.root.join('public', 'uploads', uploaded_io.original_filename), 'wb') do |file|
  file.write(uploaded_io.read)
end

I get the following TypeError, but no Encoding error. On the other hand, the file uploads.

TypeError: can't cast ActionDispatch::Http::UploadedFile to string:

Any suggestions for what I'm doing wrong? It'd be nice to see this work before I move to Paperclip or CW

Upvotes: 3

Views: 2821

Answers (1)

kaplan
kaplan

Reputation: 4229

I figured out that I was using the column :image for the upload, but during the uploading the :image is not a :string, it's an ActionDispatch::Http::UploadedFile object (right?). In the database the :image column field type is a :string. So what I want to store in :image is the uploaded_io.original_filename.

My first solution to make it work was not use ':image' as the f.file_field in the form_for. I'm calling it :filename instead, then grab the uploaded_io.original_filename from that object and store it in :image, then do my save.

This is ugly, but it works.

uploaded_io = params[:piture][:filename]
File.open(Rails.root.join('public', 'uploads', uploaded_io.original_filename), 'wb') do |file|
  file.write(uploaded_io.read)
end
@picture.image = uploaded_io.original_filename

I'm still a little hazy on the file.write(upload_io.read) vs File.open(...)

Upvotes: 3

Related Questions