Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails 4 - How to have image upload in froala editor with carrierwave?

I'm stuck on what to do for having image upload in froala editor. I have carrierwave working for uploading images to google cloud storage for other sections of my app and now I want to have image uploads in froala editor working as well.

Here is what I've done so far

Post image uplaoder

class PostImageUploader < CarrierWave::Uploader::Base

  # Choose what kind of storage to use for this uploader:
   storage :fog

  # Override the directory where uploaded files will be stored.
  # This is a sensible default for uploaders that are meant to be mounted:
  def store_dir
    "post-image"
  end


  # Add a white list of extensions which are allowed to be uploaded.
  # For images you might use something like this:
   def extension_white_list
     %w(jpg jpeg gif png)
   end

  # Override the filename of the uploaded files:
  # Avoid using model.id or version_name here, see uploader/store.rb for details.
  def filename
   "#{model.id}-#{original_filename}" if original_filename.present?
  end

end

I made a post image model

class PostImage < ActiveRecord::Base
  belongs_to :post
  mount_uploader :image, PostImageUploader
  validate  :image_size

    # Validates the size of an uploaded picture.
    def image_size
      if image.size > 5.megabytes
        errors.add(:picture, "should be less than 5MB")
      end
    end

end

I made attach and detach methods in my post controller but i don't know what to put in them.

 def attach
 end

 def detach
 end

 def image_params
   params.require(:post_image).permit(:image)
 end

Made routes to the attach and detach methods but they could be wrong because im not sure if I even need the methods.

match '/guides/:guide_id/posts/attach' => 'posts#attach', :via => :create, as: :attach_guide_post_image
match '/guides/:guide_id/posts/detach'=> 'posts#detach', :via => :delete, as: :detach_guide_post_image

my carriwewave initializer is setup and working (because I'm using it on other places on the site) so I dont think I need to add it in. And I dont think I need to add my post controller new and create methods, their pretty stock standard.

From here I went to the froala docs for image uploads, but I dont know what values to put in and which I do need and which I don't need. My questions are the comments written in capital letters.

 <script>
  $(function() {
    $('.editor')
      .froalaeditor({
        // Set the image upload parameter.
        imageUploadParam: 'image',
        // 1. I'M GUESSING THIS IS THE PARAM PASSED

        // Set the image upload URL.
        imageUploadURL: <%= attach_guide_post_image_path =%>,
        // 2. MADE THIS PATH IN THE ROUTES


        // Set request type.
        imageUploadMethod: 'POST',

        // Set max image size to 5MB.
        imageMaxSize: 5 * 1024 * 1024,

        // Allow to upload PNG and JPG.
        imageAllowedTypes: ['jpeg', 'jpg', 'png', 'gif']
      })
      .on('froalaEditor.image.beforeUpload', function (e, editor, images) {
        // Return false if you want to stop the image upload.

        //3. SO I PUT ERROR MESSAGE IN THESE?? IF SO SHOULD IT BE A POPUP OR TEXT ON THE SCREEN AND HOW
      })
      .on('froalaEditor.image.uploaded', function (e, editor, response) {
        // Image was uploaded to the server.
      })
      .on('froalaEditor.image.inserted', function (e, editor, $img, response) {
        // Image was inserted in the editor.
      })
      .on('froalaEditor.image.replaced', function (e, editor, $img, response) {
        // Image was replaced in the editor.
      })
      .on('froalaEditor.image.error', function (e, editor, error, response) {
        // Bad link.
        else if (error.code == 1) { ... }

        // No link in upload response.
        else if (error.code == 2) { ... }

        // Error during image upload.
        else if (error.code == 3) { ... }

        // Parsing response failed.
        else if (error.code == 4) { ... }

        // Image too text-large.
        else if (error.code == 5) { ... }

        // Invalid image type.
        else if (error.code == 6) { ... }

        // Image can be uploaded only to same domain in IE 8 and IE 9.
        else if (error.code == 7) { ... }

        // Response contains the original server response to the request if available.
      });
  });
</script>

This is what I got. I know basic JS and have been using rails for about 6 months so im fairly new to it. I have never done anything like this in rails and js and cant find a solid guide on it.

Above is what I got and im stuck. Would love some help on what needs to be done from there to get image uploads working.

like image 336
Rob Avatar asked May 30 '16 05:05

Rob


People also ask

Is Froala Editor good?

Froala WYSIWYG HTML Editor is the best rich text editor out there. It is built using the latest technologies and taking the great advantages of jQuery and HTML5 to create an outstanding editing experience.

What is the Froala editor?

Froala Editor is a lightweight WYSIWYG HTML Editor written in Javascript that enables rich text editing capabilities for your applications. Its complete documentation, specially designed framework plugins and tons of examples make it easy to integrate.


2 Answers

I struggled with this same problem and decided to bypass carrierwave entirely and just upload directly to S3 as follows:

      $('.post-editor').froalaEditor({
          toolbarBottom: true,
          toolbarButtons: ['bold', 'italic', 'underline', 'fontFamily', 'fontSize', 'paragraphFormat', 'align', 'formatOL', 'formatUL', 'insertLink', 'insertImage', 'insertVideo'],
          imageUploadToS3: {
            bucket: "<%= @hash[:bucket] %>",
            region: 's3-us-west-1',
            keyStart: "<%= @hash[:key_start] %>",
            callback: function (url, key) {},
            params: {
              acl: "<%= @hash[:acl] %>", // ACL according to Amazon Documentation.
              AWSAccessKeyId: "<%= @hash[:access_key] %>", // Access Key from Amazon.
              policy: "<%= @hash[:policy] %>", // Policy string computed in the backend.
              signature: "<%= @hash[:signature] %>", // Signature computed in the backend.
            }
          }
        })  

Set up an initializer in config/initializers/AWS_CONFIG.rb:

AWS_CONFIG = {
  'access_key_id' => ENV["S3_ACCESS_KEY"],
  'secret_access_key' => ENV["S3_SECRET_KEY"],
  'bucket' => 'froala-bucket',
  'acl' => 'public-read',
  'key_start' => 'uploads/'
}

Set up the Amazon signature in lib/amazon_signature.rb:

module AmazonSignature
  extend self

  def signature
    Base64.encode64(
        OpenSSL::HMAC.digest(
          OpenSSL::Digest.new('sha1'),
          AWS_CONFIG['secret_access_key'], self.policy
        )
      ).gsub("\n", "")
  end

  def policy
    Base64.encode64(self.policy_data.to_json).gsub("\n", "")
  end

  def policy_data
    {
      expiration: 10.hours.from_now.utc.iso8601,
      conditions: [
        ["starts-with", "$key", AWS_CONFIG['key_start']],
        ["starts-with", "$x-requested-with", "xhr"],
        ["content-length-range", 0, 20.megabytes],
        ["starts-with", "$content-type", ""],
        {bucket: AWS_CONFIG['bucket']},
        {acl: AWS_CONFIG['acl']},
        {success_action_status: "201"}
      ]
    }
  end

  def data_hash
    {:signature => self.signature, :policy => self.policy, :bucket => AWS_CONFIG['bucket'], :acl => AWS_CONFIG['acl'], :key_start => AWS_CONFIG['key_start'], :access_key => AWS_CONFIG['access_key_id']}
  end
end

And finally call it in your PostsController:

before_action :set_hash_for_froala

...

def set_hash_for_froala
  @hash = AmazonSignature::data_hash
end

This video was very helpful: http://rubythursday.com/episodes/ruby-snack-23-froala-wysiwyg-saving-images-on-amazon-s3

like image 140
Lorenz Avatar answered Nov 15 '22 04:11

Lorenz


I made this about an year ago. [Setting up Froala WYSIWYG editor with CarrierWave and Rails].

I'll try to answer this based on your case.

You can save the file in action attach in your post controller. I assume the model is "PostImage" with "image" attribute from your post. This is the controller looks like:

def attach
    @postimage = PostImage.new
    @postimage.image = params[:file]
    @postimage.save

    respond_to do |format|
        format.json { render :json => { status: 'OK', link: @postimage.image.url}}
    end 
end

Simply call the method in your javascript initializer

<script>
    $(function() {
        $('.selector').froalaEditor({
            // Set the image upload URL.
            imageUploadURL: '<%= attach_guide_post_image_path =%>.json',
            imageUploadMethod: 'POST'
        })
    }
</script>

Hope this helps.

like image 36
Nate Cheng Avatar answered Nov 15 '22 06:11

Nate Cheng