Days
Hours
Minutes
Seconds
x

Froala Editor v4.2.0 is Here LEARN MORE

Skip to content

Ruby on Rails

Image Upload

The following code example illustrates how to handle image upload on your server using Ruby as a server-side language. For step by step explanation of the upload flow see image upload concept.

Frontend

The main index page.

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">

  <!-- Include external CSS. -->
  <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.4.0/css/font-awesome.min.css" rel="stylesheet" type="text/css" />
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.25.0/codemirror.min.css">

  <!-- Include Editor style. -->
  <link href="https://cdn.jsdelivr.net/npm/[email protected]/css/froala_editor.pkgd.min.css" rel="stylesheet" type="text/css" />
  <link href="https://cdn.jsdelivr.net/npm/[email protected]/css/froala_style.min.css" rel="stylesheet" type="text/css" />
</head>

<body>
  <!-- Include external JS libs. -->
  <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
  <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.25.0/codemirror.min.js"></script>
  <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.25.0/mode/xml/xml.min.js"></script>

  <!-- Include Editor JS files. -->
  <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/[email protected]//js/froala_editor.pkgd.min.js"></script>
  <div class="sample">
    <h2>Image upload example.</h2>
    <form>
      <textarea id="edit" name="content"></textarea>
    </form>
  </div>

  <!-- Initialize the editor. -->
  <script>
    $(function() {
      $('#edit').froalaEditor({
        // Set the image upload URL.
        imageUploadURL: '/upload_image',

        imageUploadParams: {
          id: 'my_editor'
        }
      })
    });
  </script>
</body>
</html>

Backend

upload_controller.rb file will manage the upload part. It has basic image format validations this can be easily extended.

The uploads directory will be automatically created if it dose not exist under public/uploads/files

After processing the uploaded image, if it passes the validation, the server will respond with a JSON object containing a link to the uploaded file.

E.g.: {"link":"http://server_address/download_file/name_of_file"}.

class UploadController < ActionController::Base

  IMAGE_EXT = [".gif", ".jpeg", ".jpg", ".png", ".svg"]

  def upload_image
    if params[:file]
      FileUtils::mkdir_p(Rails.root.join("public/uploads/files"))

      ext = File.extname(params[:file].original_filename)
      ext = image_validation(ext)
      file_name = "#{SecureRandom.urlsafe_base64}#{ext}"
      path = Rails.root.join("public/uploads/files/", file_name)

      File.open(path, "wb") {|f| f.write(params[:file].read)}
      view_file = Rails.root.join("/download_file/", file_name).to_s
      render :json => {:link => view_file}.to_json

    else
      render :text => {:link => nil}.to_json
    end
  end

  def image_validation(ext)
    raise "Not allowed" unless IMAGE_EXT.include?(ext)
  end

  def access_file
    if File.exists?(Rails.root.join("public", "uploads", "files", params[:name]))
      send_data File.read(Rails.root.join("public", "uploads", "files", params[:name])), :disposition => "attachment"
    else
      render :nothing => true
    end
  end
end

routes.rb file will manage the routing part.

Inside this file you need to define the routes for the POST image upload and the GET uploaded image requests

Rails.application.routes.draw do
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html

post "/upload_image" => "upload#upload_image", :as => :upload_image
get "/download_file/:name" => "upload#access_file", :as => :upload_access_file, :name => /.*/
[class^="wpforms-"]
[class^="wpforms-"]
[bws_google_captcha]
<div class="gglcptch gglcptch_v2"><div id="gglcptch_recaptcha_839859971" class="gglcptch_recaptcha"></div> <noscript> <div style="width: 302px;"> <div style="width: 302px; height: 422px; position: relative;"> <div style="width: 302px; height: 422px; position: absolute;"> <iframe src="https://www.google.com/recaptcha/api/fallback?k=6Ld6lNoUAAAAAM626LfCOrnkBFJtYZAKESFCjgv_" frameborder="0" scrolling="no" style="width: 302px; height:422px; border-style: none;"></iframe> </div> </div> <div style="border-style: none; bottom: 12px; left: 25px; margin: 0px; padding: 0px; right: 25px; background: #f9f9f9; border: 1px solid #c1c1c1; border-radius: 3px; height: 60px; width: 300px;"> <textarea id="g-recaptcha-response" name="g-recaptcha-response" class="g-recaptcha-response" style="width: 250px !important; height: 40px !important; border: 1px solid #c1c1c1 !important; margin: 10px 25px !important; padding: 0px !important; resize: none !important;"></textarea> </div> </div> </noscript></div>
[class^="wpforms-"]
[class^="wpforms-"]
[bws_google_captcha]
<div class="gglcptch gglcptch_v2"><div id="gglcptch_recaptcha_558518913" class="gglcptch_recaptcha"></div> <noscript> <div style="width: 302px;"> <div style="width: 302px; height: 422px; position: relative;"> <div style="width: 302px; height: 422px; position: absolute;"> <iframe src="https://www.google.com/recaptcha/api/fallback?k=6Ld6lNoUAAAAAM626LfCOrnkBFJtYZAKESFCjgv_" frameborder="0" scrolling="no" style="width: 302px; height:422px; border-style: none;"></iframe> </div> </div> <div style="border-style: none; bottom: 12px; left: 25px; margin: 0px; padding: 0px; right: 25px; background: #f9f9f9; border: 1px solid #c1c1c1; border-radius: 3px; height: 60px; width: 300px;"> <textarea id="g-recaptcha-response" name="g-recaptcha-response" class="g-recaptcha-response" style="width: 250px !important; height: 40px !important; border: 1px solid #c1c1c1 !important; margin: 10px 25px !important; padding: 0px !important; resize: none !important;"></textarea> </div> </div> </noscript></div>
[class^="wpforms-"]
[class^="wpforms-"]
[bws_google_captcha]
<div class="gglcptch gglcptch_v2"><div id="gglcptch_recaptcha_489850777" class="gglcptch_recaptcha"></div> <noscript> <div style="width: 302px;"> <div style="width: 302px; height: 422px; position: relative;"> <div style="width: 302px; height: 422px; position: absolute;"> <iframe src="https://www.google.com/recaptcha/api/fallback?k=6Ld6lNoUAAAAAM626LfCOrnkBFJtYZAKESFCjgv_" frameborder="0" scrolling="no" style="width: 302px; height:422px; border-style: none;"></iframe> </div> </div> <div style="border-style: none; bottom: 12px; left: 25px; margin: 0px; padding: 0px; right: 25px; background: #f9f9f9; border: 1px solid #c1c1c1; border-radius: 3px; height: 60px; width: 300px;"> <textarea id="g-recaptcha-response" name="g-recaptcha-response" class="g-recaptcha-response" style="width: 250px !important; height: 40px !important; border: 1px solid #c1c1c1 !important; margin: 10px 25px !important; padding: 0px !important; resize: none !important;"></textarea> </div> </div> </noscript></div>