[Fixed] Unable to upload images with Rails PaperClip GEM equipped with Angular 9+

Issue

I am using rails as a backend and angular as a frontend. I want to save images to rails backend. I decided to use the paperclip gem. Here is the error below.

↳ app/controllers/products_controller.rb:49:in `set_product’
Unpermitted parameters: :id, :created_at, :updated_at,
:image_file_name, :image_content_type, :image_file_size,
:image_updated_at

Here is some model for angular.

export class Product {
  public image:File;
  ...//the rest of the variables
}

Here is where I set the value of the products image.

public fileSelected(event) {
    this.product.image=event.target.files[0];
  }

Then I use the httpclient angular functions to send it. That all is working so I wont show it unless requested. Only with an image does this fail.

On the rails side. Here is the paperclip migration

class AddAttachmentImageToProducts < ActiveRecord::Migration[6.0]
  def self.up
    change_table :products do |t|
      t.attachment :image
    end
  end

  def self.down
    remove_attachment :products, :image
  end
end

My model

class Product < ActiveRecord::Base
  has_attached_file :image, styles: { medium: "300x300>", thumb: "100x100>" }, default_url: "/images/:style/missing.png"
  validates_attachment :image, presence: true
  do_not_validate_attachment_file_type :image
end

My controller

class ProductsController < ApplicationController
  before_action :set_product, only: [:show, :update, :destroy]

  # GET /products
  def index
    @products = Product.all

    render json:  @products.to_json
  end
  # GET /products/1
  def show
    render json: @products.image
  end

  # POST /products
  def create
    @products = Product.new(product_params)

    if @products.save
      render json: @products, status: :created, location: @products
    else
      render json: @products.errors, status: :unprocessable_entity
    end
  end

  # PATCH/PUT /products/1
  def update
    if @products.update(product_params)
      render json: @products
    else
      render json: @products.errors, status: :unprocessable_entity
    end
  end

  # DELETE /products/1
  def destroy
    @products.destroy
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_product
      @products = Product.find(params[:id])
    end

    # Only allow a trusted parameter "white list" through.
    def product_params
      params.require(:product).permit(:name, :description, :image)

    end
end


Solution

If you are using Rails API, then you should use paperclip adapters to save the image. You have to send base64 file front end.

 def update
   @products.name = params[:product][:name]
   @products.description = params[:product][:description]
   image_base = params[:product][:image] ###base64 text of your image came from front-end
   image = Paperclip.io_adapters.for(image_base)
   image.original_filename = "image" ###Name of the file, you can take it from parameters / you can assign it statically
   @products.image = image
   if @products.save
      ##Do your stuff
   else
     render json: @products.errors, status: :unprocessable_entity
   end
 end

In case if you get any exceptions after adding above code in your controller, create a config/initializers/paperclip.rb file and place the following code in that initializer

  Paperclip::DataUriAdapter.register
  require 'paperclip/media_type_spoof_detector'
  module Paperclip
   class MediaTypeSpoofDetector
    def spoofed?
     false
    end
   end
  end

Leave a Reply

(*) Required, Your email will not be published