Paperclip for both images and Videos - ruby-on-rails

In my app I already have paperclip for upload images, but requirement changed in order to accept both images and videos. The images are already defined in a model with a belongs_to relationship, called Attachment. Since the video will also be an attachment of the same parent model (in my case, articles) I wanted to reuse the same Attachment model for images & videos. Is this a good idea?
The code of my attachment.rb is:
class Attachment < ActiveRecord::Base
belongs_to :article
has_attached_file :url, :s3_protocol => :https ,
styles: {
medium: "300x300>", thumb: "100x100>", big: "1200x1200>", normal: "600x600>"
}
validates_attachment_content_type :url, content_type: /\Aimage|\Avideo\/.*\Z/
validates_attachment :url, content_type: { content_type: ["image/jpeg", "image/gif", "image/png", "video/mp4"] }
end
But as it is, it's not storing videos on the S3. I get the following in the terminal
Command :: file -b --mime '/var/folders/v_/pf2bsxnj1y37ccd2pjksv7z80000gn/T/f3e2afc957bb9fb2aa3e77e69359c48920160131-13311-pyeez1.mp4'
Command :: identify -format '%wx%h,%[exif:orientation]' '/var/folders/v_/pf2bsxnj1y37ccd2pjksv7z80000gn/T/8dc7385648e2164764b72fda6fd9099a20160131-13311-1l40ccn.mp4[0]' 2>/dev/null
[paperclip] An error was received while processing: #<Paperclip::Errors::NotIdentifiedByImageMagickError: Paperclip::Errors::NotIdentifiedByImageMagickError>
Command :: identify -format '%wx%h,%[exif:orientation]' '/var/folders/v_/pf2bsxnj1y37ccd2pjksv7z80000gn/T/8dc7385648e2164764b72fda6fd9099a20160131-13311-1l40ccn.mp4[0]' 2>/dev/null
[paperclip] An error was received while processing: #<Paperclip::Errors::NotIdentifiedByImageMagickError: Paperclip::Errors::NotIdentifiedByImageMagickError>
Command :: identify -format '%wx%h,%[exif:orientation]' '/var/folders/v_/pf2bsxnj1y37ccd2pjksv7z80000gn/T/8dc7385648e2164764b72fda6fd9099a20160131-13311-1l40ccn.mp4[0]' 2>/dev/null
[paperclip] An error was received while processing: #<Paperclip::Errors::NotIdentifiedByImageMagickError: Paperclip::Errors::NotIdentifiedByImageMagickError>
Command :: identify -format '%wx%h,%[exif:orientation]' '/var/folders/v_/pf2bsxnj1y37ccd2pjksv7z80000gn/T/8dc7385648e2164764b72fda6fd9099a20160131-13311-1l40ccn.mp4[0]' 2>/dev/null
[paperclip] An error was received while processing: #<Paperclip::Errors::NotIdentifiedByImageMagickError: Paperclip::Errors::NotIdentifiedByImageMagickError>
Command :: file -b --mime '/var/folders/v_/pf2bsxnj1y37ccd2pjksv7z80000gn/T/f3e2afc957bb9fb2aa3e77e69359c48920160131-13311-kvb5nr.mp4'
The second question is since I'm using AngularJS for the frontend, can I just take advantage of HTML <video> tag to render the video to the user?

Looks like the issue is that ImageMagick is trying to transcode the video, which it cannot.
The way to handle transcoding of videos within Paperclip is to use the paperclip-av-transcoder gem (formerly paperclip-ffmpeg). I only have experience with the latter:
#app/models/attachment.rb
class Attachment < ActiveRecord::Base
has_attached_file :url, :s3_protocol => :https ,
styles: lambda { |a| a.instance.is_image? ? medium: "300x300>", thumb: "100x100>", big: "1200x1200>", normal: "600x600>" } : {:thumb => { :geometry => "100x100#", :format => 'jpg', :time => 10}, :medium => { :geometry => "300x300#", :format => 'jpg', :time => 10}}}, processors: [:transcoder]
validates_attachment :url,
content_type: ['video/mp4'],
message: "Sorry, right now we only support MP4 video",
if: :is_video?
validates_attachment :url,
content_type: ['image/png', 'image/jpeg', 'image/jpg', 'image/gif'],
message: "Different error message",
if: :is_image?
private
def is_video?
url.instance.attachment_content_type =~ %r(video)
end
def is_image?
url.instance.attachment_content_type =~ %r(image)
end
end
Our old code & ref

Related

Can't save image from API with paperclip

I want to save an image from my react app in my rails app.
I post this to my api:
and when I try to save it i get this error:
{
"file":[
"has contents that are not what they are reported to be",
"file type is not acceptable"
],
"file_content_type":[
"file type is not acceptable"
]
}
my model looks like this:
class Photo < ApplicationRecord
validates :title, presence: true
belongs_to :user
has_attached_file :file, styles: { square: "350x233#", medium: "300x300>", thumb: "100x100>" }, default_url: "/images/:style/missing.png"
validates_attachment_content_type :file, content_type: /\Aimage\/.*\z/, message: 'file type is not acceptable'
validates_attachment_size :file, less_than: 10.megabytes, message: 'file size is more than 50MB'
end
and my controller:
def create
uploaded_file = false
if params[:photo][:image]
tempfile = Tempfile.new(params[:photo][:filename])
tempfile.binmode
tempfile.write(Base64.decode64(params[:photo][:image]))
uploaded_file = ActionDispatch::Http::UploadedFile.new(
:tempfile => tempfile,
:filename => params[:photo][:filename],
:original_filename => params[:photo][:filename],
:content_type => Mime::Type.lookup_by_extension(File.extname(params[:photo][:filename])[1..-1]).to_s
)
params[:photo][:file] = uploaded_file
end
params[:photo][:title] = params[:photo][:filename] if params[:photo][:title] == ""
# #picture = Photo.new(photo_params)
#photo = current_user.photos.build photo_params
#photo.save
render json: #photo.errors
end
and in my logs i found this:
Unpermitted parameters: :image, :filename
Command :: file -b --mime '/tmp/homepage.jpg20180415-7-1wa7yr3'
[paperclip] Trying to link /tmp/homepage.jpg20180415-7-1wa7yr3 to /tmp/ba3988db0a3167093b1f74e8ae4a8e8320180415-7-jpgu5m.jpg
[paperclip] Trying to link /tmp/ba3988db0a3167093b1f74e8ae4a8e8320180415-7-jpgu5m.jpg to /tmp/ba3988db0a3167093b1f74e8ae4a8e8320180415-7-147ntu1.jpg
Command :: file -b --mime '/tmp/ba3988db0a3167093b1f74e8ae4a8e8320180415-7-147ntu1.jpg'
[paperclip] Content Type Spoof: Filename homepage.jpg (application/octet-stream from Headers, ["image/jpeg"] from Extension), content type discovered from file command: application/octet-stream. See documentation to allow this combination.
[1m[35m (1.5ms)[0m [1m[35mBEGIN[0m
[paperclip] Trying to link /tmp/ba3988db0a3167093b1f74e8ae4a8e8320180415-7-jpgu5m.jpg to /tmp/ba3988db0a3167093b1f74e8ae4a8e8320180415-7-ndp9hd.jpg
Command :: file -b --mime '/tmp/ba3988db0a3167093b1f74e8ae4a8e8320180415-7-ndp9hd.jpg'
[paperclip] Content Type Spoof: Filename homepage.jpg (application/octet-stream from Headers, ["image/jpeg"] from Extension), content type discovered from file command: application/octet-stream. See documentation to allow this combination.
I didn't get my mistake. Can anyone help me with that upload?
I think the content_type is missing, but I don't know where.
Have you tried using Paperclip's io_adapter to decode the base64 into the attachment object? Something along the lines of:
def create
file = Paperclip.io_adapters.for(params[:photo][:image])
file.original_filename = params[:photo][:filename]
#photo = Photo.new(file: file, user: current_user)
#photo.save
end

how to load and validate the video using paperclip-Rails

please help solve the problem.
using a paperclip I organized upload images. it works.
Now I would like to organize a video upload. I changed this model:
model:
class Video < ActiveRecord::Base
validates :title, presence: true
validates :video, presence: true
belongs_to :user
has_attached_file :video,
:styles => { :medium => "300x300>", :thumb => "100x100>" },
:default_url => "/images/:style/missing.png"
validates_attachment_content_type :video, :content_type => /\Avideo\/.*\Z/
validates_attachment_file_name :video, :matches => [/3gp\Z/, /mp4\Z/, /flv\Z/]
validate :file_size_validation, :if => "video?"
def file_size_validation
errors[:video] << "should be less than 2MB" if video.size.to_i > 30.megabytes
end
end
video controller:
def create
#video = Video.new(video_params)
if #video.save
#video.update_attributes(user: current_user)
flash[:success] = :video_created
redirect_to #video
else
flash.now[:error] = :user_not_created
render 'new'
end
end
form:
<%= form_for(#video) do |f| %>
<%= f.text_field :title %>
<%= f.file_field :video %>
<%= f.submit %>
<% end %>
after attempting to upload the video I get the console the following error message:
Started POST "/videos" for 127.0.0.1 at 2015-07-23 14:17:32 +0300
Processing by VideosController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"RF3w8PzZ9LZ4pdqRPqRvHMQ+nYDL4om0YHAMlzTm8tf3iFmVmKxXSYKap3C0ogEnOkifm9i01oXs/rTX9zmtPA==", "video"=>{"title"=>"tty", "video"=>#<ActionDispatch::Http::UploadedFile:0x007f6624f10770 #tempfile=#<Tempfile:/tmp/RackMultipart20150723-13428-u7s8i8.flv>, #original_filename="mmm.flv", #content_type="video/x-flv", #headers="Content-Disposition: form-data; name=\"video[video]\"; filename=\"mmm.flv\"\r\nContent-Type: video/x-flv\r\n">}, "commit"=>"Create Video"}
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT 1 [["id", 8]]
Command :: file -b --mime '/tmp/c4efd5020cb49b9d3257ffa0fbccc0ae20150723-13428-6gn39i.flv'
Command :: identify -format '%wx%h,%[exif:orientation]' '/tmp/c4efd5020cb49b9d3257ffa0fbccc0ae20150723-13428-1eailfd.flv[0]' 2>/dev/null
[paperclip] An error was received while processing: #<Paperclip::Errors::NotIdentifiedByImageMagickError: Paperclip::Errors::NotIdentifiedByImageMagickError>
Command :: identify -format '%wx%h,%[exif:orientation]' '/tmp/c4efd5020cb49b9d3257ffa0fbccc0ae20150723-13428-1eailfd.flv[0]' 2>/dev/null
[paperclip] An error was received while processing: #<Paperclip::Errors::NotIdentifiedByImageMagickError: Paperclip::Errors::NotIdentifiedByImageMagickError>
(0.2ms) BEGIN
Command :: file -b --mime '/tmp/c4efd5020cb49b9d3257ffa0fbccc0ae20150723-13428-khstwa.flv'
(0.2ms) ROLLBACK
on screen displays the following error message:
Video Paperclip::Errors::NotIdentifiedByImageMagickError
wherein imageMagik installed in my system:
sudo apt-get install imagemagick
db:
create_table "videos", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "title"
t.integer "user_id"
t.string "video_file_size"
t.string "video_updated_at"
t.string "video_file_name"
t.string "video_content_type"
end
Working with image with paperclip and with video is different.Though the common point is that it will help you tu send the uploaded data to the server but you need to handle it with some processor.Just like you use ImageMagick for images,you should use FFMPEG to encode/decode video.
i will share the code which i usually use for video..but before that ,you must set up ffmpeg to handle all formats of video just like you did for Imagemagick.
here is set up for ffmpeg and dont forget to provide path in environment file using which ffmpeg
you need ffmpeg-paperclip as well for coding/decoding videos.
video.rb
##using s3
##convert the video into mp4 and also get screenshot of video at 5 sec
##add your own formats that you want
has_attached_file :video,
:styles => {
:mp4video => { :geometry => '520x390', :format => 'mp4',
:convert_options => { :output => { :vcodec => 'libx264',
:vpre => 'ipod640', :b => '250k', :bt => '50k',
:acodec => 'libfaac', :ab => '56k', :ac => 2 } } },
:preview => { :geometry => '300x300>', :format => 'jpg', :time => 5 }
},
processors: [:ffmpeg],
:storage => :s3,
:size => { :in => 0..25.megabytes },
:s3_permissions => :public_read,
:s3_credentials => S3_CREDENTIALS
validates_attachment_content_type :video, :content_type => /\Avideo\/.*\Z/
validates_presence_of :video
once you have saved the video,you need to use some plugins to show the video player along with your video in show action.You can use Mediaelement.js(my favorite).Download it,dump it in js/css files accordingly,Include it in application.js and application.css.
in your show.html.erb
##add video tag to show video
<video autobuffer="autobuffer" preload="auto" style="width:100%;height:100%;" controls="controls" width="100%" height="100%" poster="<%= #video.video.url(:preview)%>" >
<source src="<%= #video.video.url%>" />
<%if #video.video.expiring_url(:mp4video).present? %>
<source type="video/mp4" src="<%= #video.video.url(:mp4video)%>" />
<%end%>
</video>
##javascript to handle video player
$('video').mediaelementplayer();
paperclip's processor is designed for images, so it cannot handle videos. You're getting the error saying that ImageMagick did not recognize this file as an image. Fair enough, it's not an image!
Still, you could write a post-processor yourself, and paperclip's github page offers an example of the syntax that would be needed to call a custom processing class:
has_attached_file :scan, :styles => { :text => { :quality => :better } },
:processors => [:ocr]
This defines a variation of the attachment called text that is obtained by processing the uploaded file with a (hypothetical) Paperclip::Ocr class with options hash { :quality => :better }
Choice of the exact conversion tool is up to you, but you do want to make sure that processing is done asynchronously, not inside the usual request-response cycle, you may want to use a background queue like Sidekiq, Que or Rails' (4.2+) ActiveJob.

How to create thumbnails only for image files with Paperclip?

I use the following code to create Assets from the uploaded files:
def upload
uploader = User.find_by_id(params[:uploader_id])
params[:assets].each do |file|
new_asset = uploader.assets.build(:asset => file) # Here the error appears
new_asset.save
end
...
end
I noticed that when I upload non-image files, e.g. my.xlsx, I got the following error:
[paperclip] identify -format %wx%h "C:/temp/stream20110628-460-3vqjnd.xlsx[0]" 2>NUL
[paperclip] An error was received while processing:
#<Paperclip::NotIdentifiedByImageMagickError: C:/temp/stream20110628-460-3vqjnd.xlsx is
not recognized by the 'identify' command.>
(For image files everything works fine: a thumbnail is created, and there is no error.)
Is that because Paperclip tries to create a thumbnail from my.xlsx ?
What configuration will create thumbnails only for image files ?
Here is some relevant code:
class Asset < ActiveRecord::Base
belongs_to :uploader, :class_name => "User"
has_attached_file :asset, :styles => { :thumb => "80x80#" }
end
I used the following nice solution:
before_post_process :image?
def image?
(asset_content_type =~ SUPPORTED_IMAGES_REGEX).present?
end
where:
SUPPORTED_IMAGE_FORMATS = ["image/jpeg", "image/png", "image/gif", "image/bmp"]
SUPPORTED_IMAGES_REGEX = Regexp.new('\A(' + SUPPORTED_IMAGE_FORMATS.join('|') + ')\Z')
Change the has_attached_file line to read:
has_attached_file :asset, :styles => { :thumb=> "80x80#" }, :whiny_thumbnails => false
This will prevent it from raising an error when thumbnails are not created. Note though that it won't raise errors if one occurs when processing an image though.

rails + paperclip + plupload

Hi i'm using paperclip and plupload like in this tutorial:
http://www.theroamingcoder.com/node/50
It works.
But if i try to set thumbnails with paperclip like:
has_attached_file :data,
:styles => { :medium => "558x418>", :thumb => "60x82>" }
It doesn't work.
I receive this error:
[paperclip] identify -format %wx%h '/tmp/stream20110209-26212-1l2obtp-0.png[0]' 2>/dev/null
[paperclip] convert '/tmp/stream20110209-26212-1l2obtp-0.png[0]' -resize "558x418>" '/tmp/stream20110209-26212-1l2obtp-020110209-26212-cl5lbg-0' 2>/dev/null
[paperclip] An error was received while processing: #<Paperclip::PaperclipError: There was an error processing the thumbnail for stream20110209-26212-1l2obtp-0>
[paperclip] identify -format %wx%h '/tmp/stream20110209-26212-1l2obtp-0.png[0]' 2>/dev/null
[paperclip] convert '/tmp/stream20110209-26212-1l2obtp-0.png[0]' -resize "60x82>" '/tmp/stream20110209-26212-1l2obtp-020110209-26212-1m6qvkj-0' 2>/dev/null
[paperclip] An error was received while processing: #<Paperclip::PaperclipError: There was an error processing the thumbnail for stream20110209-26212-1l2obtp-0
How can i solve it?
thanks
It looks like you don't have Imagemagick installed!
http://www.imagemagick.org/script/index.php
If I am wrong try this
has_attached_file :data, :styles => { :medium => ["558x418>", :png], :thumb => ["60x82>", :png] }
I had to disable chunks in plupload

rails routes using picnik with paperclip

I've been trying to get picnik to work with paperclip so I can resize and touch up images, however have had some difficulty so far.
I'm a bit confused over the routing, as I get an error:
Started POST "/products/3/photos/4" for 208.88.21.57 at Fri Dec 10 14:44:59 -0800 2010
ActionController::RoutingError (No route matches "/products/3/photos/4"):
This is when I try to pass the file back from picnik, however simply updating the image title on the same record using the exact same path seems to work fine and uses the exact same routing as above:
Started POST "/products/3/photos/4" for 69.149.172.21 at Fri Dec 10 14:52:29 -0800 2010
Processing by PhotosController#update as HTML
Parameters: {"photo"=>{"title"=>"Front"}, "commit"=>"Update Photo", "product_id"=>"3", "authenticity_token"=>"uZ3dV3BCSm7GvP39U51KCClx2P8gIWktyki/3rnpOIM=", "utf8"=>"\342\234\223", "id"=>"4"}
[paperclip] Saving attachments.
Redirected to http://leatherarts.heroku.com/products/3
Completed 302 Found in 17ms
What am I missing?
I ignored the authenticity token in the controller for the update action... btw
Picnik takes a basic params to submit back to by post, my line looks like this:
<%= link_to "Edit or Crop", "http://www.picnik.com/service/?_import=img&img=#{#photo.data.url(:original)}&_export=#{url_for(product_photo_url(#product,#photo))}&_export_field=photos_attributes&_export_title=SaveIt&_apikey=617c5c06600b6c21ebf0bc91eafbbae5" %>
Photo Model
has_attached_file :data,
:storage => 's3',
:s3_credentials => "#{RAILS_ROOT}/config/s3_credentials.yml",
:bucket => 'leatherarts.com',
:s3_host_alias => 'leatherarts.com.s3.amazonaws.com',
:url => ':s3_alias_url',
:path => "images/products/:product_id/:style/:basename.:extension",
:styles => { :thumb => "60x60#", :small => "200x200>", :medium => "400x400>", :large => "1000x1000>" },
:default_style => :original,
:default_url => 'http://leatherarts.com.s3.amazonaws.com/images/records/m1.png',
:s3_headers => { 'Expires' => 2.months.from_now.httpdate }
validates_attachment_presence :data
validates_attachment_size :data, :less_than => 10.megabytes
validates_attachment_content_type :data, :content_type => ['image/jpeg','image/gif','image/png']
UPDATE:
I got past the first problem with a specified PUT in a new route:
match 'products/:product_id/photos/:id/picnik' => 'photos#picnik', :as => :picnik
but still can't quite get it to all fall together. It seems to work and save, but it never saves the updated image.
I added this action in my photo controller
def picnik
#product = Product.find(params[:product_id])
#photo = Photo.find(params[:id])
#photo.data(params[:data])
if #photo.save
flash[:notice] = "Successfully updated photo."
redirect_to product_path(#product)
else
render :action => 'edit'
end
end
And according to the log it seems to do what it should:
Started POST "/products/10/photos/25/picnik" for 208.88.21.59 at Sat Dec 11 08:09:32 -0800 2010
Processing by PhotosController#picnik as HTML
Parameters: {"data"=>#<File:/home/slugs/372051_88c7fa8_e87f-144ddfc3-a58b-4233-939c-2131aa001145/mnt/tmp/RackMultipart20101211-7501-1tdkwuq-0>, "product_id"=>"10", "id"=>"25"}
[paperclip] identify -format %wx%h '/home/slugs/372051_88c7fa8_e87f-144ddfc3-a58b-4233-939c-2131aa001145/mnt/tmp/paperclip-reprocess20101211-7501-1fo13g4-0[0]' 2>/dev/null
[paperclip] convert '/home/slugs/372051_88c7fa8_e87f-144ddfc3-a58b-4233-939c-2131aa001145/mnt/tmp/paperclip-reprocess20101211-7501-1fo13g4-0[0]' -resize "x60" -crop "60x60+15+0" +repage '/home/slugs/372051_88c7fa8_e87f-144ddfc3-a58b-4233-939c-2131aa001145/mnt/tmp/paperclip-reprocess20101211-7501-1fo13g4-020101211-7501-42lphg-0' 2>/dev/null
[paperclip] identify -format %wx%h '/home/slugs/372051_88c7fa8_e87f-144ddfc3-a58b-4233-939c-2131aa001145/mnt/tmp/paperclip-reprocess20101211-7501-1fo13g4-0[0]' 2>/dev/null
[paperclip] convert '/home/slugs/372051_88c7fa8_e87f-144ddfc3-a58b-4233-939c-2131aa001145/mnt/tmp/paperclip-reprocess20101211-7501-1fo13g4-0[0]' -resize "1000x1000>" '/home/slugs/372051_88c7fa8_e87f-144ddfc3-a58b-4233-939c-2131aa001145/mnt/tmp/paperclip-reprocess20101211-7501-1fo13g4-020101211-7501-1nskgrl-0' 2>/dev/null
[paperclip] identify -format %wx%h '/home/slugs/372051_88c7fa8_e87f-144ddfc3-a58b-4233-939c-2131aa001145/mnt/tmp/paperclip-reprocess20101211-7501-1fo13g4-0[0]' 2>/dev/null
[paperclip] convert '/home/slugs/372051_88c7fa8_e87f-144ddfc3-a58b-4233-939c-2131aa001145/mnt/tmp/paperclip-reprocess20101211-7501-1fo13g4-0[0]' -resize "400x400>" '/home/slugs/372051_88c7fa8_e87f-144ddfc3-a58b-4233-939c-2131aa001145/mnt/tmp/paperclip-reprocess20101211-7501-1fo13g4-020101211-7501-fpe5rc-0' 2>/dev/null
[paperclip] identify -format %wx%h '/home/slugs/372051_88c7fa8_e87f-144ddfc3-a58b-4233-939c-2131aa001145/mnt/tmp/paperclip-reprocess20101211-7501-1fo13g4-0[0]' 2>/dev/null
[paperclip] convert '/home/slugs/372051_88c7fa8_e87f-144ddfc3-a58b-4233-939c-2131aa001145/mnt/tmp/paperclip-reprocess20101211-7501-1fo13g4-0[0]' -resize "200x200>" '/home/slugs/372051_88c7fa8_e87f-144ddfc3-a58b-4233-939c-2131aa001145/mnt/tmp/paperclip-reprocess20101211-7501-1fo13g4-020101211-7501-v5e99x-0' 2>/dev/null
[paperclip] saving images/products/10/original/DSC_0212.JPG
[paperclip] saving images/products/10/etsy/DSC_0212.JPG
[paperclip] saving images/products/10/thumb/DSC_0212.JPG
[paperclip] saving images/products/10/medium/DSC_0212.JPG
[paperclip] saving images/products/10/small/DSC_0212.JPG
[paperclip] Saving attachments.
Redirected to http://leatherarts.heroku.com/products/10
Completed 302 Found in 1632ms
But it's always the same image as before, with no new adjustments from picnik? I thought maybe it was the S3 Caching, but I created a new size category and it created it with the old image just the same.

Resources