I need a plugin for "Upload Videos" in a rails application.
Can anyone give me an idea on how to do it?
You can also use carrierwave gem
Add in your Gemfile: gem 'carrierwave'
Run bundle install
Create an uploader for uploading video using carrierwave generator.
rails g uploader video
It creates file video_uploader.rb in uploaders directory
Create a migration in model where you want attach the video or image, be careful with the migration name it should be like add_{column}_to_{model}
rails g migration add_video_to_post video:string
Migrate database
Run rake db:migrate
Add uploader to the model
class Post < ActiveRecord::Base
mount_uploader :video, VideoUploader
end
Add video parameter in PostController
class PostController < ApplicationController
.
.
.
def post_params
params.require(:post).permit(:name,:video)
end
end
Add file attachment field in _forml.html.erb which is in views/posts
<%=f.file_field :video%>
To view/stream the video
<% #posts.each do |post|%>
<%= post.name %>
<%= video_tag post.video_url.to_s :controls =>true %>
<%end%>
for more information
carrierwave gem
https://github.com/carrierwaveuploader/carrierwave
and video tutorial
http://railscasts.com/episodes/253-carrierwave-file-uploads
Even more specific, I created a Rails gem that works specifically with videos:
https://rubygems.org/gems/paperclip-ffmpeg
Try paperclip gem, very popular for this purpose
Related
I need to get the path to the file on disk which is using ActiveStorage. The file is stored locally.
When I was using paperclip, I used the path method on the attachment which returned the full path.
Example:
user.avatar.path
While looking at the Active Storage Docs, it looked like rails_blob_path would do the trick. After looking at what it returned though, it does not provide the path to the document. Thus, it returns this error:
No such file or directory # rb_sysopen -
Background
I need the path to the document because I am using the combine_pdf gem in order to combine multiple pdfs into a single pdf.
For the paperclip implementation, I iterated through the full_paths of the selected pdf attachments and load them into the combined pdf:
attachment_paths.each {|att_path| report << CombinePDF.load(att_path)}
Use:
ActiveStorage::Blob.service.path_for(user.avatar.key)
You can do something like this on your model:
class User < ApplicationRecord
has_one_attached :avatar
def avatar_on_disk
ActiveStorage::Blob.service.path_for(avatar.key)
end
end
I'm not sure why all the other answers use send(:url_for, key). I'm using Rails 5.2.2 and path_for is a public method, therefore, it's way better to avoid send, or simply call path_for:
class User < ApplicationRecord
has_one_attached :avatar
def avatar_path
ActiveStorage::Blob.service.path_for(avatar.key)
end
end
Worth noting that in the view you can do things like this:
<p>
<%= image_tag url_for(#user.avatar) %>
<br>
<%= link_to 'View', polymorphic_url(#user.avatar) %>
<br>
Stored at <%= #user.image_path %>
<br>
<%= link_to 'Download', rails_blob_path(#user.avatar, disposition: :attachment) %>
<br>
<%= f.file_field :avatar %>
</p>
Thanks to the help of #muistooshort in the comments, after looking at the Active Storage Code, this works:
active_storage_disk_service = ActiveStorage::Service::DiskService.new(root: Rails.root.to_s + '/storage/')
active_storage_disk_service.send(:path_for, user.avatar.blob.key)
# => returns full path to the document stored locally on disk
This solution feels a bit hacky to me. I'd love to hear of other solutions. This does work for me though.
You can download the attachment to a local dir and then process it.
Supposing you have in your model:
has_one_attached :pdf_attachment
You can define:
def process_attachment
# Download the attached file in temp dir
pdf_attachment_path = "#{Dir.tmpdir}/#{pdf_attachment.filename}"
File.open(pdf_attachment_path, 'wb') do |file|
file.write(pdf_attachment.download)
end
# process the downloaded file
# ...
end
After uploading a file, we would like to make the file available for view and download. The file could be in common format such as pdf, jpg or xls. After a user clicks the file name, the file is downloaded and opened by local app on user's PC. Here is what we did:
<%= link_to r.file_name, r.storage_subdir + '/' + r.file_name %>
r.storage_subdir returns storage/multi_item_orderx_order/15. storage is a subdir under root. r.file_name returns IMG_3002.jpg
When clicking the file name, there pops up an error:
No route matches [GET] "/upload/storage/multi_item_orderx_order/15/IMG_3002.jpg"
(Not sure how upload was put in front of storage). Used save link as to download and the file is only a partial in size and there shows nothing after clicking it. What is the right way to both view and download a file? Or at least to download a file.
If you don't understand how to render uploaded file then you uploading it wrong. Here is a small tutorial for you.
How to implement file upload function in your rails application
First of all add this gems to your Gemfile and then execute bundle install in console.
gem "rmagick"
gem "carrierwave"
Let's imagine that you have model User and you need to give users ability to upload profile picture. When bundler install successfuly installed new gems we need to create Uploader via generator.
rails g uploader avatar
And let's configure it:
class AvatarUploader < CarrierWave::Uploader::Base
include CarrierWave::RMagick
storage :file
def store_dir
"uploads/#{mode.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
version :thumb do
process resize_to_limit: [64, 64]
end
end
Few words about this configuration: we said carrierwave to use RMagick gem, said which storage we would like to use and where data must be stored and implemented resize for thumbnails.
Now need to add column avatar to users table. Let's create migration:
rails g migration add_avatar_to_users avatar:string
And now lets mount our uploader in User model:
class User < ActiveRecord::Base
mount_uploader :avatar, AvatarUploader
end
That's all! Carrierwave configured and ready to use in your application! Now you can create view like:
<%= form_for #user, html: {multipart: true} do |f| %>
<%= f.file_field :avatar %>
<%= f.submit %>
<% end %>
This form will give you ability to upload avatar. In controller you need to pass params[:user][:avatar] to model to create\update user's avatar.
And if you need to render image to view you can use something like this:
<%= image_tag #user.avatar_url(:thumb) %>
or
<%= image_tag #user.avatar.thumb.url %>
Don't forget to install imagemagick headers via system's package manager (apt-get \ yum \ pacman \ brew \ etc) because if you will not do it, bundler will fall.
If you got any questions, check out carrierwave github page and carrierwave documentation.
I have a rails 4 app. I am uploading assets using Carrierwave and it allows me to save resized versions as well as the original. If I upload 'myimage.jpg' it will also save 'xs_myimage.jpg' to AWS S3. The problem is, the xs version name isn't stored anywhere, so I don't know how to serve that image.
This is my image call in the view:
<%= image_tag (#portfolio.img) %>
Some how I'd like to call the xs_myimage.jp:
<%= image_tag 'xs_'(#portfolio.img)%> #I know this doesn't work, its just what I've tried
Carrierwave will automatically generate an URL helper for every version of the asset you declare. Consider this:
class MyUploader < CarrierWave::Uploader::Base
version :xs do
# ...
end
end
You can then use the generated helper:
uploader = MyUploader.new # or get the instance out of your model (#portfolio.img)
uploader.xs.url
In Carrierwave uploader
version :xs do
process resize_to_limit: [50, 50]
end
then in view
<%= image_tag(#portfolio.img.xs.url) %>
Try to use this
<%
parts = #portfilio.img.split('/')
parts[-1]="xs_#{parts.last}"
img = parts.join('/')
%>
<%= image_tag img %>
But its very bad solution.
If "xs" is a smaller(bigger) size of image why you doesn't use carrierwave thumbs?
I'm building a file management system using the Paperclip gem and I need to download file.
What would be the parameters of the link_to method?
I have the following line in my model:
has_attached_file :box
Suppose your model is Boxholder
If you have #boxholder instance variable in your controller like:
#boxholder = Boxholder.find(params[:id])
Then the following line could be your solution:
<%= link_to #boxholder.box_file_name,#boxholder.box.url %>
I'm working on Rails 4 project that I need to store some images uploadaded directly by the users, and I must be capable of create a images gallery where a single user can only view their own uploads.
I'm uploading files with the CArrierWave gem, and it's doing fine. I'm changed the default uploads directory ( the public folder ) to a custom folder of mine ( /uploads/.....), but I think I'll not be able to show the images cause the 'uploads' folder can't be accessed directly, but I dont want to let the images on the public folder cause I don't want them to be freely accessed by anyone.
Code of my view
<div>
<%= #photos.each do |p| %>
<div>
<%= image_tag (p.path_url) %>
</div>
<% end %>
</div>
My CarrierWave uploader class:
class PhotoupUploader < CarrierWave::Uploader::Base
storage :file
def store_dir
"../app/uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.album_id}"
end
and Photo model:
class Photo < ActiveRecord::Base
belongs_to :album
attr_accessible :legend, :path
mount_uploader :path, PhotoupUploader
end
How can I proceed?
Thanks
You would need to serve your images straight from the controller (see this question on how: Rendering an image):
def image
render :text => open(File.join('/uploads', user_id, params[:image_id], "rb").read
end
Usage:
<% image_tag "image?image_id=154" %>