how to load and validate the video using paperclip-Rails - ruby-on-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.

Related

Paperclip security validation error mp4

I am using Paperclip to upload videos and keep getting a Security Validation error about the content type
The error when saving an mp4 to my model class is "content type discovered from file command: video/mp4. See documentation to allow this combination."
The save looks like this
AssignmentEventVideo.create(video: "https://s3-ap-southeast-2.amazonaws.com/dev/upload/0c857445-09ad-44b6-bbfa-810a9974a501/ScreenCaptureProject4.mp4")
The model class
class AssignmentEventVideo < ActiveRecord::Base
has_attached_file :video, :styles => {
:medium => { :geometry => "640x480", :format => 'mp4' },
:android => { :geometry => "640x480", :format => 'webm'},
:mobile => { :geometry => "300x300", :format => 'png', :time => 2 },
:thumb => { :geometry => "100x100#", :format => 'png', :time => 2 }
}
validates_attachment_content_type :video, content_type: ['video/mp4']
end
If have tried disabling validation all together with the code below but it still throws the error
do_not_validate_attachment_file_type :video
I have confirmed that the file command is return the correct type with
file -b --mime ScreenCaptureProject3.mp4
which returns
video/mp4; charset=binary
The save is working fine for another model class that accepts images and checks content using
validates_attachment_content_type :photo, content_type: /\Aimage\/.*\Z/
I'm not sure where to turn next - except to recreate the class and change the column name to something that doesn't clash with video?
Hope someone can help!
Thanks katafrakt - you got me on the right path.
I was using a presigned_post and uploading to S3 using JQuery FileUploader. This was not setting the Content-Type and I was getting back a binary/octet type that Paperclip didn't know how to deal with.
I set content_type on the presigned post, which stores the right meta data in S3 and all is well.

Paperclip doesn't store in a proper format fetched image by url

When I trying to fetch a facebook image by the graph URL(https://graph.facebook.com), paperclip stores avatar_image_name as "picture" in the database. The example of code:
img = UserImages.new
img.avatar = URI.parse('https://graph.facebook.com/666980153384194/picture?type=large')
img.save
The MySQL query in a console log:
=> #<URI::HTTPS:0x00000009954490 URL:https://graph.facebook.com/666980153384194/picture?type=large>
irb(main):009:0> img.save
(0.0ms) BEGIN
SQL (0.0ms) INSERT INTO `user_images` (`avatar_content_type`, `avatar_file_name`, `avatar_file_size`, `avatar_updated
_at`, `created_at`, `updated_at`) VALUES ('image/jpeg', 'picture', 6157, '2014-07-08 13:55:53', '2014-07-08 13:56:02', '
2014-07-08 13:56:02')
(29.1ms) COMMIT
As you can see fetched image file stored by the name 'picture'. But if to fetch image by Direct URL like:
https://scontent-a-lax.xx.fbcdn.net/hphotos-prn2/v/t1.0-9/10478546_662150043867205_2640371404472615909_n.jpg?oh=cb2fe9d421fef3d7d2220bb48a2a36e2&oe=5418E8FB
The fetched image stored as:
(0.0ms) BEGIN
Command :: file -b --mime "C:/Users/Windows/AppData/Local/Temp/f1620d075c0642a77f7b98e532d8a8eb20140708-1040-1h5z4e6.jpg
"
SQL (1.0ms) INSERT INTO `user_images` (`avatar_content_type`, `avatar_file_name`, `avatar_file_size`, `avatar_updated
_at`, `created_at`, `updated_at`) VALUES ('image/jpeg', '10478546_662150043867205_2640371404472615909_n.jpg', 25862, '20
14-07-08 14:02:45', '2014-07-08 14:02:49', '2014-07-08 14:02:49')
(34.1ms) COMMIT
=> true
Any advise(solution) will be highly appreciated.
The source of UserImages class:
class UserImages < ActiveRecord::Base
belongs_to :imageable ,polymorphic: true
has_attached_file :avatar,
:styles => { :medium => "300x300>", :thumb => "125x125>" },
:path => ":rails_root/public/images/users/:id/:style/:hash.:extension",
:default_url => "/images/normal/missing.jpg",
:url => "/images/users/:id/:style/:hash.:extension",
:hash_secret => "EWRWerrew234UTY"
validates_attachment :avatar, :content_type => { :content_type => ["image/jpeg", "image/gif", "image/png"] },
:size => { :in => 0..5.megabytes }
end
There is no problem in both fetching URLs.... Both working fine...
The difference is only because paperclip generates the file name from the last part of the URL...
So in the first URL
https://graph.facebook.com/666980153384194/picture?type=large
And in the second URL
https://scontent-a-lax.xx.fbcdn.net/hphotos-prn2/v/t1.0-9/10478546_662150043867205_2640371404472615909_n.jpg?oh=cb2fe9d421fef3d7d2220bb48a2a36e2&oe=5418E8FB
I've bolded the part of the URL that paperclip is using to generate filename.... And in both cases you shouldn't really bother yourself with the file name... Since you can do any operation you want thought paperclip.
And you can make sure that the files are uploaded by checking the path public/images/users/:id (the paperclip path configuration)

Generate Thumbnail From pdf in rails paperclip

How can I generate the first page of a pdf as a thumbnail in paperclip?
I tried a lot but it's not working
has_attached_file :book_url, :styles => {
:thumb => "100x100#",
:small => "150x150>",
:medium => "200x200" }
This is giving the name of the pdf as a link but it's not giving the first page of the pdf
<%= link_to 'My PDF', #book.book_url.url %>
Tadas' answer is right, but for those who need more context, you can do something like this: The model below only creates thumbnails for certain kinds of files (e.g. it doesn't make thumbnails of audio files), but does make thumbnails for pdfs, image files, and video files:
class Record < ActiveRecord::Base
print self # for logging on heroku
belongs_to :user
# Ensure user has provided the required fields
validates :title, presence: true
validates :file_upload, presence: true
validates :description, presence: true
# Use the has_attached_file method to add a file_upload property to the Record
# class.
has_attached_file :file_upload,
# In order to determine the styles of the image we want to save
# e.g. a small style copy of the image, plus a large style copy
# of the image, call the check_file_type method
styles: lambda { |a| a.instance.check_file_type },
processors: lambda {
|a| a.is_video? ? [ :ffmpeg ] : [ :thumbnail ]
}
# Validate that we accept the type of file the user is uploading
# by explicitly listing the mimetypes we are willing to accept
validates_attachment_content_type :file_upload,
:content_type => [
"video/mp4",
"video/quicktime",
"image/jpg",
"image/jpeg",
"image/png",
"image/gif",
"application/pdf",
"audio/mpeg",
"audio/x-mpeg",
"audio/mp3",
"audio/x-mp3",
"file/txt",
"text/plain",
"application/doc",
"application/msword",
"application/vnd.ms-excel",
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"application/vnd.ms-powerpoint"
],
:message => "Sorry! We do not accept the attached file type"
# Before applying the Imagemagick post processing to this record
# check to see if we indeed wish to process the file. In the case
# of audio files, we don't want to apply post processing
before_post_process :apply_post_processing?
# Helper method that uses the =~ regex method to see if
# the current file_upload has a content_type
# attribute that contains the string "image" / "video", or "audio"
def is_image?
self.file_upload.content_type =~ %r(image)
end
def is_video?
self.file_upload.content_type =~ %r(video)
end
def is_audio?
self.file_upload.content_type =~ /\Aaudio\/.*\Z/
end
def is_plain_text?
self.file_upload_file_name =~ %r{\.(txt)$}i
end
def is_excel?
self.file_upload_file_name =~ %r{\.(xls|xlt|xla|xlsx|xlsm|xltx|xltm|xlsb|xlam|csv|tsv)$}i
end
def is_word_document?
self.file_upload_file_name =~ %r{\.(docx|doc|dotx|docm|dotm)$}i
end
def is_powerpoint?
self.file_upload_file_name =~ %r{\.(pptx|ppt|potx|pot|ppsx|pps|pptm|potm|ppsm|ppam)$}i
end
def is_pdf?
self.file_upload_file_name =~ %r{\.(pdf)$}i
end
def has_default_image?
is_audio?
is_plain_text?
is_excel?
is_word_document?
end
# If the uploaded content type is an audio file,
# return false so that we'll skip audio post processing
def apply_post_processing?
if self.has_default_image?
return false
else
return true
end
end
# Method to be called in order to determine what styles we should
# save of a file.
def check_file_type
if self.is_image?
{
:thumb => "200x200>",
:medium => "500x500>"
}
elsif self.is_pdf?
{
:thumb => ["200x200>", :png],
:medium => ["500x500>", :png]
}
elsif self.is_video?
{
:thumb => {
:geometry => "200x200>",
:format => 'jpg',
:time => 0
},
:medium => {
:geometry => "500x500>",
:format => 'jpg',
:time => 0
}
}
elsif self.is_audio?
{
:audio => {
:format => "mp3"
}
}
else
{}
end
end
end
I think I once got it working by enforcing a file type, e.g.
:thumb => ["100x100#", :png]
of course it's not ideal, because it enforces this filetype for every upload
Thanks a million to #duhaime for his beautiful answer.
Since this is the most complete source of information I found to have PDF attached, I'd like to document it further:
Requirements:
imagemagick
ghostscript (I forgot about this one)
(optional) ffmpeg if you want to handle video files
Also I replaced has_default_image? and apply_post_processing? with the single:
def can_thumbnail?
self.check_file_type.try(:{], :thumb).present?
end
Finally I created a method for the not-thumbable attachments:
def thumb
return self.file.url(:thumb) if self.can_thumbnail?
if self.is_video?
'/thumb/video.png'
else
'/thumb/default.png'
end
end
But thanks again #duhaime

Paperclip - No route matches GET

Paperclip 2.7
Ruby 1.8.7 Enterprise
Rails 3.1.0
Imagemagick 6.6
When i upload an image im my app, they are correctly processed by imagemagick and they are stored in conrrectly path. But, when i need to take this file to show, is not found.
Saving image:
Started POST "/p" for 177.16.57.105 at Sun Sep 23 23:39:16 -0300 2012
Processing by ProductsController#create as HTML
Parameters: {"commit"=>"Salvar", "authenticity_token"=>"EgBUGfKIIduS2lkl0mh5p27pT0vF0/P8HXO852KHMM8=", "utf8"=>"â", "product"=>{"photo"=>#>, "price"=>"", "name"=>"Brigadeiro de pistache", "product_type"=>"1", "featured"=>"0", "description"=>"Brigadeiro de pistache"}}
[32mCommand[0m :: convert '/tmp/stream20120923-19588-vw8u1s-020120923-19588-3lym39-0[0]' -resize "120x80>" '/tmp/stream20120923-19588-vw8u1s-020120923-19588-3lym39-020120923-19588-16ky3i8-0'
[paperclip] Saving attachments.
[paperclip] saving /home/brigaderiagourmand/apps_rails/site/public/system/photos/24/short/brigadeirocolorido.png
Redirected to http://brigaderiagourmand.com.br/p/24
Completed 302 Found in 257ms
And when i need take the file...
Started GET "/photos/original/missing.png" for 177.16.57.105 at Sun Sep 23 23:39:17 -0300 2012
ActionController::RoutingError (No route matches [GET] "/photos/original/missing.png"):
My model
class Product < ActiveRecord::Base
attr_accessible :name, :description, :price, :photo, :product_type, :featured
attr_accessor :photo_file_name
has_attached_file :photo, :styles => { :thumb => "50x50>", :medium => "280x180>", :large => "585x400>", :short => "120x80>", :original => "200,200>" }
TYPES = ["Belga", "Normal"]
end
Form views
= form_for #product, :html => {:multipart => true} do |f|
= f.file_field :photo
Show view
= image_tag #product.photo.url(:original)
Is the output from processing the image complete?
In your output paperclip only re-sizes to short (120x80>)
Your get request is trying to load the missing.jpg which is a default for image if the the requested couldn't be found. Take a look into /home/brigaderiagourmand/apps_rails/site/public/system/photos/24/ and see if there are the other re-sized photos.
There is a great screencast from Ryan Bates about paperclip
Hope this helps you

How to specify :path and :url to save img in Paperclip, Rails 3.0.12

I'm using Paperclip with my Rails 3.0 app in order to add an avatar to a user, and it won't save the image because the paths are off. Heres what I get:
Started GET "/profilepics/small/missing.png" for 127.0.0.1 at 2012-04-11 23:38:29 -0700
ActionController::RoutingError (No route matches "/profilepics/small/missing.png"):
My user model has:
has_attached_file :profilepic, :styles => { :small => "150x150>" }
What should I put for :path => & :url => ?
Form looks like :
<% form_for #user, :html => { :multipart => true } do |f| %>
<%= f.file_field :profilepic %>
<% end %>
Logs look like :
Started GET "/system/profilepics/small/missing.png" for 127.0.0.1 at 2012-04-12 00:33:51 -0700
ActionController::RoutingError (No route matches "/system/profilepics/small/missing.png"):
Rendered /usr/lib/ruby/gems/1.9.1/gems/actionpack-3.0.12/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (1.2ms)
See my sample:
has_attached_file :avatar, :styles => { :thumb => "50x50#", :large => "1000x1000>", :medium => "200x200#" },
:default_url => "/system/avatars/:style/missing.png",
:url => "/system/:attachment/:id/:style_:filename",
:path => ":rails_root/public/system/:attachment/:id/:style_:filename"
:default_url - is the path for the default image, when the user didn't upload any avatar
"#" - this symbol is to crop image
then you can show your images as such:
<%=image_tag(#user.avatar.url(:thumb))%>
<%=image_tag(#user.avatar.url(:medium))%>
Works now!!!
For people struggling with the same issue, here's a few important things to ALWAYS make sure and check:
In your form, always specify { :multipart => true } otherwise, the form won't accept file attachments.
<%= form_for #user, :html => **{ :multipart => true }** do |f| %>
In your user.rb (or whatever model you want to add attachments to ), make attr_accessible :photo (or whatever you name your attachment)
ALWAYS restart your server after installing a new Gem.
:) Thanks guys!!!!
There is no need to given url and path option if you simply want to display an image.
Use this line in show page and it will display image...
<%=image_tag(#user.profilepic.url(:small))%>
And enjoy..............

Resources