Hi! Thanks for visiting my blog. If you've received any value from my content would you mind supporting my new startup by downloading our browser add-on? It's called PriceBlink and makes online shopping a breeze. You can watch it in action here and download it for Chrome, Firefox, IE, or Safari by going to PriceBlink.com. Thank you and I hope you enjoy!

Ruby on Rails File Upload

Jan 18

I’ve been experimenting a good bit with Ruby on Rails’ file upload capabilities. Overall I’ve been very impressed with the ease of use when it comes to uploading a file and writing it to disk. Of course anything is easy once you know how. Ruby’s syntax is very different than what you’re probably used to. While I’m by no means an expert on the subject I would definitely recommend the following books:

Programming Ruby: The Pragmatic Programmers’ Guide
Agile Web Development with Rails

After digging up the necessary code I was able to experiment with ROR’s file upload capabilities. My method called create was attached to my controller and looked like:

def create
File.open(“/Users/db/_dev/rails/videos/swing.mov”, “w”){|f|f.write(@params["video"].read)}
end

With that one line of code the file was written to disk….not too shabby. It’s right up there with ColdFusion’s CFFILE which has a much cleaner tag-based approach. At any rate, using this method allowed me to upload all sorts of photos and videos with ease.

I then proceeded to strain the server a little bit. When I say server ROR is running locally on my Powerbook. I grabbed a 175MB video file and put it to the test. The upload took almost 5 minutes to complete and during this time the output of top displayed ROR’s CPU utilization at about 80%. Pretty heavy lifting, but the upload competed successfully and I was able to view the uploaded file without any hiccups.

6 comments

  1. Joe Cairns /

    Hi, thanks for the tip on the file upload technique. One problem will crop up if you are developing on a windows machine.

    The line:
    File.open(”/Users/db/_dev/rails/videos/swing.mov”, “w”)

    Should be changed to:
    File.open(”/Users/db/_dev/rails/videos/swing.mov”, “wb”)

    Windows, unlike linux, unix, and mac, does not assume a created file is a binary, it assumes a text file. By adding the “b” to the parameters you are forcing the file to be a binary. I don’t know whether using the “b” option will cause a non-windows install problems or not though.

    -Joe

  2. Hey Joe, thanks for the great info. I don’t normally develop my Rails apps on Windows, but will keep this in mind the next time I do. I’ll test the “b” parameter on my Mac and Linux to see if it causes any problems. If not, I’ll use it by default so that my code is compatible across different operating systems. Thanks again.

  3. I really would want to see how you created everything, from the model, view and controller etc. I’m a rails noob and also would want to see full/complete code. Tnx a lot!!!

  4. #create a unique file name using timestamp Month/Day/Year/Hour/Minute/Seconds and filename
    newname= Time.now.strftime(“%m%d%y%H%M%S”).to_s +”#{file.original_filename}”
    #with linux you may have to put the complete Path – also take the wb attribute and make it just ‘w’
    File.open(“/path/to/folder/#{newname}”, “w”) { |f| f.write(file.read) }

  5. OK, I’ve been playing around with this a good deal myself. The problem I’m having is with storing it in the database for later use. If I use multipart, the name of the file isn’t stored, instead it stores something like:
    --- !ruby/object:StringIO {}
    Any ideas?

  6. Jason, here is some code from the model of one of my applications. This saves the file to disk and then returns the file name, width, and height. I hope this helps and let me know if you have any questions.

    def self.save_user_photo(photo, user_id)
    time = Time.now.to_i
    image_name = “#{user_id}_#{time}_#{rand(10000000)}”
    image_path = “#{PHOTO_UPLOAD_DIR}#{image_name}”

    # Write the original image to disk
    File.open(“#{image_path}.jpg”, “wb”) do |file|
    file.puts photo.read
    end

    # Create the default image
    img = Magick::Image::read(“#{image_path}.jpg”).first

    # Get the aspect ratio
    aspect_ratio = img.columns.to_f/img.rows.to_f

    # Create the profile photo with a max width of 480 and variable height based on aspect ratio
    if img.columns.to_f > 640
    new_height = (640/aspect_ratio).round
    photo = img.scale(640, new_height)
    else
    photo = img.scale(img.columns, img.rows)
    end

    # Overwrite the uploaded photo with the smaller one
    photo.write(“#{image_path}.jpg”)

    # Create the thumbnail, don’t size it up if it’s too small
    if img.columns.to_f > 200
    thumb = img.scale(200, (200/aspect_ratio).round)
    else
    thumb = img.scale(img.columns, img.rows)
    end

    # Write the thumbnail photo
    thumb.write(“#{image_path}_thumb.jpg”)

    # Return image name, width, and height
    [image_name, photo.columns, photo.rows]
    end

Trackbacks/Pingbacks

  1. [db75] » Blog Archive » Ruby on Rails Command Line Access - [...] I’ve been digging around for a while trying to find a way for Ruby on Rails to access the ...

Leave a Reply