I have a project in rails 4 that uses ckeditor with cloudinary. The uplaod to Cloudinary works fine, but after the upload, when the editor should lad the image, I get the error:
NoMethodError - undefined method `gsub' for nil:NilClass:
My CKEditor Picture Uploader is:
# encoding: utf-8
class CkeditorPictureUploader < CarrierWave::Uploader::Base
include Ckeditor::Backend::CarrierWave
include Cloudinary::CarrierWave
include CarrierWave::MiniMagick
[:extract_content_type, :set_size, :read_dimensions].each do |method|
define_method :"#{method}_with_cloudinary" do
send(:"#{method}_without_cloudinary") if self.file.is_a?(CarrierWave::SanitizedFile)
{}
end
alias_method_chain method, :cloudinary
end
process :read_dimensions
# Create different versions of your uploaded files:
version :thumb do
process :resize_to_fill => [118, 100]
end
version :content do
process :resize_to_limit => [800, 800]
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
Ckeditor.image_file_types
end
end
When I go to upload and click on "find image on server" the image is there and I can load the image on editor, but not when I upload image to server
Someone got this problem before?
Thanks!
This error occurs because gsub could not find url for Uploaded image in ckeditor. You have to create ckeditor asset_response.rb file in your lib/ckeditor folder of your App and put this line of code
def asset_url(relative_url_root)
#ckeditor_assets = Ckeditor::Picture.last.url_content
puts #ckeditor_assets.inspect
#return nil if asset.url_content.nil?
url = #ckeditor_assets #Ckeditor::Utils.escape_single_quotes(asset.url_content)
if URI(url).relative?
"#{relative_url_root}#{url}"
else
url
end
end
put the whole code and replace asset_url method with this.
This is just a hack to include Ckeditor::Picture model.
Put this code for cloudinary in CkeditorPictureUploader file
include Ckeditor::Backend::CarrierWave
include Cloudinary::CarrierWave
process :tags => ["photo_album_sample"]
process :convert => "jpg"
version :thumbnail do
eager
resize_to_fit(200, 200)
cloudinary_transformation :quality => 80
end
From #t-s 's answer, I found that in Ckeditor::AssetResponse#asset_url
method, the asset object is not reloaded, so asset.content_url will always be nil thus caused the error. I fixed it like this:
class Ckeditor::Picture < Ckeditor::Asset
...
def url_content
url(:content) || begin
if persisted?
reload
url(:content)
end
end
end
end
And similarly for Ckeditor::AttachmentFile class if you have it.
Related
I am using CarrierWave + rmagick gems to upload image to server. When I am uploading a normal file, everything goes fine. But when I upload malformed file, the form error doesn't display CarrierWave error, it displays the error which appears when running rmagick.
A simple example. I have User model, and an uploader inside it like that:
class User < ActiveRecord::Base
...
mount_uploader :avatar, PictureUploader
end
(the avatar is a stringfield)
Now, the uploader is defined here:
class BaseImageUploader < CarrierWave::Uploader::Base
include CarrierWave::RMagick
storage :fog
def extension_white_list
%w(jpg jpeg gif png)
end
end
class PictureUploader < BaseImageUploader
def default_url
'placeholder.png'
end
def store_dir
'images/pictures'
end
version :thumb do
process resize_to_fit: [50, 50]
end
version :medium do
process resize_to_fill: [400, 400]
end
version :small_square do
process resize_to_fill: [200, 200]
end
end
Then I create an empty file, for example, with touch ~/Desktop/file.jpg, and trying to upload it via the form, and here I am getting a validation error:
Avatar Failed to manipulate with rmagick, maybe it is not an image? Original Error: Empty input file `<foldername>/public/uploads/tmp/1470905765-10111-5893/thumb_file.jpg' # error/jpeg.c/JPEGErrorHandler/322
I tried using ming_magick instead of rmagick, but the result is the same (with slightly different error message)
Can I do something to alter this validation message to say something like Avatar Your image is invalid instead of the default?
Hm, actually that was pretty easy: I just needed to add a string to i18n, like that:
errors.messaging.rmagick_processing_error: "Error processing image"
I've been trying to use RMagick auto_orient method to fix mobile uploads. Currently they are rotated 90 degrees. My uploader file currently looks like this.
class AvatarUploader < CarrierWave::Uploader::Base
include CarrierWave::RMagick
storage :fog
def root
Rails.root.join 'public/'
end
include CarrierWave::MimeTypes
process :set_content_type
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
process :resize_to_fill => [200, 200]
version :thumb do
process :resize_to_fill => [50, 50]
end
process :auto_orient
def extension_white_list
%w(jpg jpeg gif png)
end
end
This is giving me an error
undefined local variable or method auto_orient for AvatarUploader:Class (NameError)
I've tried several solutions,
exif image rotation issue using carrierwave and rmagick to upload to s3, https://github.com/minimagick/minimagick/issues/68
but no dice.
Anyone got a clue what I'm doing wrong?
Try adding the following:
def auto_orient
manipulate! do |img|
img.auto_orient!
end
end
As it stands now, the auto_orient process you're referencing doesn't exist in the context, hence the error.
Edit: according to the imagemagick github link you posted, auto_orient! might be broken. You could then use auto_orient instead in a similar way (it just creates a new image instead of modifying the one passed to the method). Refer to the links you posted for possible solutions using the auto_orient method.
This is my Uploader:
class PhotoUploader < CarrierWave::Uploader::Base
include CarrierWave::MiniMagick
process :resize_to_fit => [nil, 600]
version :thumb do
process :resize_to_fill => [150,150]
end
# Choose what kind of storage to use for this uploader:
storage :file
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
def cache_dir
"#{Rails.root}/tmp/uploads"
end
def extension_white_list
%w(jpg jpeg gif png)
end
def filename
if original_filename
#name ||= Digest::MD5.hexdigest(current_path)
"#{#name}.#{file.extension}"
end
end
end
In production.rb, I set config.serve_static_assets = false.
And I then deployed this project on a production server(Nginx + Passenger) using Capistrano. When I upload a picture, it will generate 2 copies under the /home/deploy/Gallary/current/public/uploads/picture/photo/ dir, just as following shows:
And I can access the first one through browser(because this one is the default file which Carrierwave generated), while the second one(generated by version :thumb) threw a exception just like this:
ActionController::RoutingError (No route matches [GET] "/uploads/picture/photo/49/thumb_6d9596c7449d3714eadb74b9c71beec2.jpg")
Actually this file thumb_6d9596c7449d3714eadb74b9c71beec2.jpg does exist in the dic right there.
So, what's wrong? And what should I do?
I had a similar problem. Found the answer in another thread.
So try this:
Server unable to find public folder in rails 3 production environment
Worked for me
I am using carrierwave_backgrounder to upload images to S3 in a background process with Sidekiq.
Here's my background_uploader.rb class...
class BackgroundUploader < CarrierWave::Uploader::Base
include ::CarrierWave::Backgrounder::Delay
include CarrierWave::RMagick
include CarrierWave::MimeTypes
process :set_content_type
# Include the Sprockets helpers for Rails 3.1+ asset pipeline compatibility:
include Sprockets::Helpers::RailsHelper
include Sprockets::Helpers::IsolatedHelper
storage :fog
def store_dir
"uploads/backgrounds/#{model.id}"
end
def default_url
"/assets/default.jpg"
end
process :resize_to_fit => [1024, 1024]
process :convert => 'jpg'
process :fix_exif_rotation
def extension_white_list
%w(jpg jpeg png)
end
def filename
#name ||= Digest::MD5.hexdigest(File.dirname(current_path.to_s))
"#{#name}.#{file.extension}" if original_filename
end
# Rotates the image based on the EXIF Orientation & applies gaussian blur
def fix_exif_rotation
manipulate! do |img|
img.auto_orient!
img = yield(img) if block_given?
img = img.gaussian_blur(0.0, 20.0)
img
end
end
end
carrierwave_backgrounder.rb:
CarrierWave::Backgrounder.configure do |c|
c.backend :sidekiq, queue: :carrierwave
end
background.rb contains:
mount_uploader :image, BackgroundUploader
process_in_background :image
I then run sidekiq -q carrierwave to fire up the background workers. All is working good! Upload a file, I see the queue accept it and start working...
If I immediately open up my AWS S3 Console I see the original file in there. Non-resized and un-blurred. Once the job is complete...I refresh S3 and there's the resized/blurred version. Now both images are in there, but I only want the blurred image to be there. In my view I use...
<%= image_tag(#background.image.to_s) %>
It displays the original file. If I check the checkbox to remove the file, it does so as it should (deletes the original from S3), but the blurred version stays there.
What's getting uploaded to S3...
original.jpg (immediate...I don't want this uploaded at all)
modified.jpg (after job completes)
Long story short: I don't want the original file to upload to S3.
I think your problem is the filename method, which carrierwave may rely on to find (and delete) the original file. Does the problem go away when you use a filename that doesn't change between when it's initially stored and when you process it?
I've got a photo upload feature in my rails app. The app uploads direct to s3 through carrierwave via rmagick and fog. The issue I am having is when a photo is uploaded via mobile through the "take a photo option" in portrait (note this is with iphone but I believe android has the same issue). Once uploaded the image appears fine on mobile, however when viewed on desktop the image appears rotated 90 degrees.
Through my research it looks to be an issue with exif. This stackoverflow responder outlines 2 potential solutions. This gist also looks promising as well.
So far I have found a few solutions posted but none have worked. Ideally I would like the photo to be saved to s3 as a portrait, then just display the image as is.
Any suggestions are well appreciated.
Below is my code
app/uploaders/image_uploader.rb
class ImageUploader < CarrierWave::Uploader::Base
include CarrierWaveDirect::Uploader
include CarrierWave::RMagick
# Include the Sprockets helpers for Rails 3.1+ asset pipeline compatibility:
include Sprockets::Helpers::RailsHelper
include Sprockets::Helpers::IsolatedHelper
include CarrierWave::MimeTypes
process :fix_exif_rotation
process :set_content_type
version :thumb do
process resize_to_fill: [200, 200]
end
def extension_white_list
%w(jpg jpeg png)
end
def fix_exif_rotation #this is my attempted solution
manipulate! do |img|
img = img.auto_orient!
end
end
end
app/models/s3_image.rb
class S3Image < ActiveRecord::Base
attr_accessible :image, :name, :user_id
mount_uploader :image, ImageUploader
belongs_to :user
def image_name
File.basename(image.path || image.filename) if image
end
class ImageWorker
include Sidekiq::Worker
def perform(id, key)
s3_image = S3Image.find(id)
s3_image.key = key
s3_image.remote_image_url = s3_image.image.direct_fog_url(with_path: true)
s3_image.save!
s3_image.update_column(:image_processed, true)
end
end
end
config/initializers/carrierwave.rb
CarrierWave.configure do |config|
config.fog_credentials = {
provider: "AWS",
aws_access_key_id: " ... ",
aws_secret_access_key: " ... "
}
config.fog_directory = " ... "
end
btw I used this Railscast as a guide for setting up my s3 upload.
Well I got this working using fog instead or carrierwave_direct.
Below is the code that ended up working for me:
app/uploaders/image_uploader.rb
class ImageUploader < CarrierWave::Uploader::Base
include CarrierWave::MiniMagick
include Sprockets::Helpers::RailsHelper
include Sprockets::Helpers::IsolatedHelper
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
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
def fix_exif_rotation #this is my attempted solution
manipulate! do |img|
img.tap(&:auto_orient)
end
end
process :fix_exif_rotation
end
app/models/s3_image.rb
class S3Image < ActiveRecord::Base
attr_accessible :image, :name, :user_id, :image_cache
mount_uploader :image, ImageUploader
belongs_to :user
end
initializers/carrierwave.rb
CarrierWave.configure do |config|
config.fog_credentials = {
provider: "AWS",
aws_access_key_id: " ... ",
aws_secret_access_key: " ... ",
region: 'us-west-2'
}
config.fog_directory = " ... "
end
I had a similar problem and fixed it with an approach nearly identical to yours.
# In the uploader:
def auto_orient
manipulate! do |img|
img = img.auto_orient
end
end
(Note that I am not calling auto_orient! - just auto_orient, without the bang.)
Then I have process :auto_orient as the first line of any version I create. For example:
version :square do
process :auto_orient
process :resize_to_fill => [600, 600]
end
My solution (quite similar to Sumeet) :
# painting_uploader.rb
process :right_orientation
def right_orientation
manipulate! do |img|
img.auto_orient
img
end
end
It's really important to return an image. Otherwise, you'll get an
NoMethodError (undefined method `write' for "":String):
Lando2319's answer was not working for me.
I am using RMagick.
I managed to make ImageMagick apply the correct orientation (and to reset the EXIF rotation data in order to avoid a double rotation by the viewer) by using :
def fix_exif_rotation # put this before any other process in the Carrierwave uploader
manipulate! do |img|
img.tap(&:auto_orient!)
end
The difference between my solution & Lando's is the bang (!). In my case it was absolutely necessary.