I am using Carrier wave to upload images. But with the default store_dir in the image_uploader.rb file, it is appending the store_dir to my image path. So I am successful in displaying the images that I have uploaded. However, I have a database with remote image urls that are already existing. These remote image urls are not displayed, as it is appending the store_dir to the image path and they are not found.
For eg:
It is taking "http://myapp.com/images/I/51oYEfb%2B0WL.SL160.jpg" as "/uploads/product/productimage/1/http%3A/myapp.com/images/I/51oYEfb%252B0WL.SL160.jpg"
Here is my code:
_product.html.erb
<% #products.each do |product| %>
<li>
<%= image_tag(product.productimage_url) if product.productimage? %>
</li>
<% end %>
Product.rb
class Product < ActiveRecord::Base
mount_uploader :productimage, ProductimageUploader
end
productimage_uploader.rb
class ProductimageUploader < CarrierWave::Uploader::Base
include CarrierWave::MiniMagick
storage :file
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
end
I even tried nil as below and it still appends / to the image url:
def store_dir
nil
end
I'm assuming you must have loaded the remote urls into your products' table's productimage column.
Perhaps the simplest way to accomplish your goal would to be add something like a remote_url column to the products table and not put remote URLs in the productimage column. Then you could do something like:
Class Product < ActiveRecord::Base
def image_url
productimage.present? ? productimage_url : remote_url
end
end
Then change your view to:
<%= image_tag(product.image_url) if product.image_url.present? %>
If your products table is already populated with remote urls from your app previously using something other than carrierwave, another option that might be better would be to write a rake task to download and re-save them with carrierwave. That might look something like:
Product.all.each do |product|
temp_location = Rails.root.join('tmp', File.basename(product.attributes['productimage']))
uri = URI(product.attributes['productimage'])
Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https') do |http|
request = Net::HTTP::Get.new uri
http.request request do |response|
File.open(temp_location, 'w') do |file|
response.read_body do |chunk|
file.write chunk
end
end
end
end
product.productimage = File.open(temp_location)
product.save!
File.unlink(temp_location)
end
Related
Controller
Save the object
How to Use This Controller to insert image in any folder and image url store in database
def create_json
#user = User.new(userFirstName: params[:userFirstName], userLastName: params[:userLastName], userEmail: params[:userEmail], password: encrypted_password, userImage: params[:userImage])
if #user.save #if save succeeds, redirect to the index action
redirect_to(:action => 'show', id: User.last.id)
else
#if not succeeds, redirect to the index action
redirect_to(:action => 'new')
end end
User(Model) mount_uploader :userImage, AvatarUploader
UsersController -> #user = User.new(user_params)
if #user.save
redirect_to(:action => 'show', id: User.last.id)
else
render :json => data_hash2, :content_type => 'application/json'
end
class AvatarUploader < CarrierWave::Uploader::Base
storage :file
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
def extension_white_list
%w(jpg jpeg gif png)
end end
If You Using Web Service
<form action="http://ruby/controllername/create" lass="new_user" id="new_user" enctype="multipart/form-data" accept-charset="UTF-8" method="post">
View following method for uploading files to app/assets/images/people_profile_images folder
First upload Image like this:
#user =User.new(user_params)
#this will create user form paramaters given
uploaded_file = params[:user][:photo]
#this will add uploaded image or file in uplaoded_fie
if (uploaded_file)
File.open(Rails.root.join('app/assets', 'images/people_profile_images', uploaded_file.original_filename), 'wb') do |file|
file.write(uploaded_file.read)
#user.photo = "/assets/people_profile_images/"+uploaded_file.original_filename
end
else
#user.photo = "/assets/people_profile_images/default_avatar.png"
end
then save user
#user.save
I don't know of an approach that can cover both: image uploading and then saving the url on the database.
You can do one or the other:
1) Use a gem called paperclip that helps upload image files.
See this links:
https://github.com/thoughtbot/paperclip#ruby-and-rails
https://teamtreehouse.com/library/image-uploads-in-ruby-on-rails-41 (paperclip, carrierwave, and dragonfly)
I have used paperclip and it has worked well for me.
OR:
2) Include it as an additional field on your filename.html.erb for your image_url
One caveat, of using this though is that this can be changed and you have no control of the image that might show on your site. Thus, the image_url should be from a reputable CDN or at least from a reputable user uploading to your site.
Create a column url:string in your model. Add it as a hidden field in your form. Set its value to the same as your remote_url using .js
var urladdy = input.remoteurl.val()
input.url.val(urladdy)
This will upload image with carrier wave and also save its url as string.
my plan is i want to create a model only for images and use that model to create profile pictures, gallery etc..
so, i have created a separate model for images and i was able to store images in display those images. but, they are too big and so i want to create a thumbnail version.
my configuration is
class Image < ActiveRecord::Base
mount_uploader :avatar, AvatarUploader
end
controller:
class ImagesController < ApplicationController
def new
#image_upload=Image.new
end
def create
#image_upload=Image.create(uploading_image)
if #image_upload.save
redirect_to '/users'
end
end
def uploading_image
params.require(:image).permit(:avatar)
end
end
uploader:
class AvatarUploader < CarrierWave::Uploader::Base
include CarrierWave::RMagick
storage :file
def store_dir
"uploads/#{model.class.to_s.underscore}...(default store only)"
end
version :thumb do
process :resize_to_limit => [50, 50]
end
user controller:
def index
#user_profile=Profile.find(1)
#imagefile=Image.first
end
users/index.html.erb:
<%= image_tag #imagefile.avatar.to_s %> #This gives me the whole image.
<%= image_tag #imagefile.image_url(:thumb).to_s %> #says undefined method `image_url' for #<Image:0x007f6cd0538010>
ps: i can see a thumbnail version in the folder
It would be so great, if anyone could help me out.
You call your other versions of the #imagefile the same way you call its original copy, just add the version name. And you can use the url helper. so:
<%= image_tag #imagefile.avatar.url %>
<%= image_tag #imagefile.avatar.thumb.url %>
<%= image_tag #imagefile.image_url(:thumb) %> should be <%= image_tag #imagefile.avatar_url(:thumb) %> as the field that has an uploader mounted is called 'avatar'. Also you shouldn't need to call .to_s on the url.
I'm trying to upload images through carrier wave, and using rails.
using minimagick.
Actually, the uploads working properly I think, but images are not shown up.
Also it shows nil value in database.
here's my code.
app/models/user.rb
class User < ActiveRecord::Base
mount_uploader :image, ImageUploader
end
mypage.html.erb (form action to "edit_complete")
<input type="file" name='image'>
users_controller.rb
def edit_complete
user = User.find(session[:user_id])
user.image = params[:image]
user.save
redirect_to :back
end
app/uploaders/image_uploader.rb
class ImageUploader < CarrierWave::Uploader::Base
include CarrierWave::MiniMagick
storage :file
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
end
No errors appeared, but nothing saved in database.
I expect image files should be saved in public/upload folder, and image file should be shown in database in rails c User.all.
However, when I upload 1.png file,
there are nothing saved, and public/upload folder is not generated.
Also in database shows nil value.
Is there any solution for this?
In file upload You need to use multipart option in form tag ie multipart option should be true in form tag.
Try something like this:
<%= form_for #user, :html => {:multipart => true} do |f| %>
<%= f.file_field :image%>
<%= f.submit 'Edit'%>
<% end %>
I am very new to ROR. I have a task to finish:
Here's the Model:
class File::DataImport < ActiveRecord::Base
attr_accessible :created_by, :file_name, :file_source, :updated_at, :updated_by
end
Here's the Controller:
class Files::DataImportsController < ApplicationController
def index
end
def new
end
end
And the views I have are index and new.
I want a field to upload data. The data should be stored in the server and save the filepath into the database in a specified column file_name. The path should be default to all uploading files.
I am stuck with how to start. Please help me to find the solution and I will learn from this.
Thanks in advance.
db/migrate/20110711000004_create_files.rb
class CreateFiles < ActiveRecord::Migration
def change
create_table :files do |t|
t.string :name
# If using MySQL, blobs default to 64k, so we have to give
# an explicit size to extend them
t.binary :data, :limit => 1.megabyte
end
end
end
app/controllers/upload_controller.rb
class UploadController < ApplicationController
def get
#file = File.new
end
end
app/views/upload/get.html.erb
<% form_for(:file,
url: {action: 'save'},
html: {multipart: true}) do |form| %>
Upload your file: <%= form.file_field("uploaded_file") %><br/>
<%= submit_tag("Upload file") %>
<% end %>
app/models/file.rb
class File < ActiveRecord::Base
def uploaded_file=(file_field)
self.name = base_part_of(file_field.original_filename)
self.data = file_field.read
end
def base_part_of(file_name)
File.basename(file_name).gsub(/[^\w._-]/, '')
end
end
app/controllers/upload_controller.rb
def save
#file = File.new(params[:file])
if #file.save
redirect_to(action: 'show', id: #file.id)
else
render(action: :get)
end
end
app/controllers/upload_controller.rb
def file
#file = File.find(params[:id])
send_data(#File.data,
filename: #File.name,
disposition: "inline")
end
app/controllers/upload_controller.rb
def show
#file = File.find(params[:id])
end
app/views/upload/show.html.erb
<h3><%= #file.name %></h3>
<img src="<%= url_for(:action => 'file', :id => #file.id) %>"/>
you should consider using one of the already available solutions like paperclip: https://github.com/thoughtbot/paperclip or carrierwave: https://github.com/jnicklas/carrierwave
Besides the Readmes there are also good tutorials out there:
http://railscasts.com/episodes/134-paperclip
http://railscasts.com/episodes/253-carrierwave-file-uploads
edit: As you want to implement it yourself I recommend examining the sources of the above on Github and try to understand what their code is doing. Also I would not bother implementing it myself, but if you have your reasons this might get you going..
You might want to look into a solution such as carrierwave.
The Github page provides a good explanation on how to use it, but this is also a nice guide.
I had a quick question. Is it possible to save a file without actually uploading it through a form?
For example, let's say I'm looking at attachments from emails, and I want to save them using a paperclip. How do I do this? Do I manually have to call a save_file(or something similar) somewhere?
Any help would be much appreciated!
I have a rake task that loads images (client logos) from a directory directly onto parperclip. You can probably adapt it to your needs.
This is my simplified Client model:
class Client < ActiveRecord::Base
LOGO_STYLES = {
:original => ['1024x768>', :jpg],
:medium => ['256x192#', :jpg],
:small => ['128x96#', :jpg]
}
has_attached_file :logo,
:styles => Client::LOGO_STYLES,
:url => "/clients/logo/:id.jpg?style=:style"
attr_protected :logo_file_name, :logo_content_type, :logo_size
Then on my rake task I do this:
# the logos are in a folder with path logos_dir
Dir.glob(File.join(logos_dir,'*')).each do |logo_path|
if File.basename(logo_path)[0]!= '.' and !File.directory? logo_path
client_code = File.basename(logo_path, '.*') #filename without extension
client = Client.find_by_code(client_code) #you could use the ids, too
raise "could not find client for client_code #{client_code}" if client.nil?
File.open(logo_path) do |f|
client.logo = f # just assign the logo attribute to a file
client.save
end #file gets closed automatically here
end
end
Regards!
The file saved in Paperclip doesn't have to be uploaded directly through a form.
I'm using Paperclip in a project to save files from URLs from webcrawler results. I'm not sure how you'd get email attachments (are they on the local file system of the server? Is your app an email app like GMail?) but as long as you can get a file stream (via something like open(URI.parse(crawl_result)) in my case...) you can attach that file to your model field that's marked has_attached_file.
This blog post about Easy Upload via URL with Paperclip helped me figure this out.
Since it now appears the original blog post is no longer available - here's the gist of it pulled from wayback machine:
This example shows a Photo model that has an Image attachment.
The technique we're using requires adding a *_remote_url (string) column for your attachment, which is used to store the original URL. So, in this case, we need to add a column named image_remote_url the photos table.
# db/migrate/20081210200032_add_image_remote_url_to_photos.rb
class AddImageRemoteUrlToPhotos < ActiveRecord::Migration
def self.up
add_column :photos, :image_remote_url, :string
end
def self.down
remove_column :photos, :image_remote_url
end
end
Nothing special is required for the controller...
# app/controllers/photos_controller.rb
class PhotosController < ApplicationController
def create
#photo = Photo.new(params[:photo])
if #photo.save
redirect_to photos_path
else
render :action => 'new'
end
end
end
In the form, we add a text_field called :image_url, so people can upload a file or provide a URL...
# app/views/photos/new.html.erb
<%= error_messages_for :photo %>
<% form_for :photo, :html => { :multipart => true } do |f| %>
Upload a photo: <%= f.file_field :image %><br>
...or provide a URL: <%= f.text_field :image_url %><br>
<%= f.submit 'Submit' %>
<% end %>
The meaty stuff is in the Photo model. We need to require open-uri, add an attr_accessor :image_url, and do the normal has_attached_file stuff. Then, we add a before_validation callback to download the file in the image_url attribute (if provided) and save the original URL as image_remote_url. Finally, we do a validates_presence_of :image_remote_url, which allows us to rescue from the many exceptions that can be raised when attempting to download the file.
# app/models/photo.rb
require 'open-uri'
class Photo < ActiveRecord::Base
attr_accessor :image_url
has_attached_file :image # etc...
before_validation :download_remote_image, :if => :image_url_provided?
validates_presence_of :image_remote_url, :if => :image_url_provided?, :message => 'is invalid or inaccessible'
private
def image_url_provided?
!self.image_url.blank?
end
def download_remote_image
self.image = do_download_remote_image
self.image_remote_url = image_url
end
def do_download_remote_image
io = open(URI.parse(image_url))
def io.original_filename; base_uri.path.split('/').last; end
io.original_filename.blank? ? nil : io
rescue # catch url errors with validations instead of exceptions (Errno::ENOENT, OpenURI::HTTPError, etc...)
end
end
Everything will work as normal, including the creation of thumbnails, etc. Plus, since we're doing all of the hard stuff in the model, "uploading" a file via URL works from within script/console as well:
$ script/console
Loading development environment (Rails 2.2.2)
>> Photo.new(:image_url => 'http://www.google.com/intl/en_ALL/images/logo.gif')
=> #<Photo image_file_name: "logo.gif", image_remote_url: "http://www.google.com/intl/en_ALL/images/logo.gif">