Rails 3, displaying jpg images from the local file system above RAILS_ROOT
For obvious reasons Rails won't allow a user to access parts of the filesystem outside of RAILS_ROOT/public
. You were actually part of the way there when you mentioned sendfile (or x-sendfile for preference.) The solution is to have Rails serve up an html page as normal which contains links to a Rails action which serves up the individual files.
For example, let's say I want to show some images from somewhere deep in the filesystem. First I have to create an action that serves up one image at a time. So in the config/routes.rb
you could add the following:
match '/serve_image/:filename' => 'images#serve'
Then I have to create a controller to match that route. For example:
class ImagesController < ApplicationController
def serve
path = "/my/servers/image/path/#{params[:filename]}"
send_file( path,
:disposition => 'inline',
:type => 'image/jpeg',
:x_sendfile => true )
end
end
Now your images are available under the url: /serve_image/my_image.jpg. So the last thing to do is create a nice html page that shows all the necessary images. It's as simple as:
<img src="/serve_image/image1.jpg">
<img src="/serve_image/image2.jpg">
<img src="/serve_image/image3.jpg">
<img src="/serve_image/image4.jpg">
Rails 3: How to get image path in Controller?
ActionController::Base.helpers.asset_path('missing_file.jpg')
Access Asset Path from Rails Controller
Unable to display remote images in rails
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
rails 5 carrierwave no route matches for image
The reason the image isn't being found is the web server's root is the Rails app's public directory, so it is looking for the image under "public/uploads/2/..."
Since the web server can't find the file it is passing the request to the Rails stack, and there is no route defined that matches, so it throws an error.
If you change your image upload root to be the public directory it should work as you expect.
UPDATE
If you don't want to put the images under the public directory you can create a route and controller action to serve the images. You can use the send_file method in the controller action. Take a look at this question:
Rails 3, displaying jpg images from the local file system above RAILS_ROOT
How Rails be configured to access a media resource that is not in its conventional directory location?
Rails does not serve these images, it lets the web server do that. You had best change the configuration of your web server to handle this scenario. If you use Apache
, for example, it would fairly easy to set up with mod_rewrite
.
Making Rails serve these images will be ugly, but it is possible if you provide a route in your routes.rb
that matches /public/images/unconventional.gif
, and if the file itself does not exist. For example:
map.connect "public/images/unconventional.gif",
:controller => "static_image_controller",
:action => "serve"
And then create a controller StaticImageController
:
class StaticImageController < ApplicationController
def serve
image = File.read(File.join(Rails.root, "unconventional.gif"))
send_data image, :type => "image/gif", :disposition => "inline"
end
end
Warning: if you use the above concept, note that if you use input from the URL to decide which file to serve (with params[:file]
, for example), you need to thoroughly sanitize the input, because you are risking exposing your entire file system to the outside world.
img src= Isn't accepting image path
The image_tag
helper prepends the path to the standard images folder into the path to the file. In my version of rails this is "/images/", so this
<%=image_tag("Flower.jpg")%>
is rendered out as
<img src="/images/Flower.jpg">
As with all resource paths like this, the actual file should be relative to your apps' public folder, ie
<RAILS ROOT>/public/images/Flower.jpg
In your version of rails it looks like the default path is /app/assets/images/
, so this
<%=image_tag("Flower.jpg")%>
is rendered out as
<img src="/app/assets/images/Flower.jpg">
which points to this file:
<RAILS ROOT>/public/app/assets/images/Flower.jpg
If you do
<img src="Flower.jpg">
it will expect the file to be in <RAILS ROOT>/public/Flower.jpg
, and obviously it's not there, so the img tag won't work. If you want to write it out yourself, without using a helper, then give the path to the file from the <RAILS ROOT/public
folder, ie
<img src="/app/assets/images/Flower.jpg">
BTW in your snippet of html you put scr="
instead of src="
which is going to break it even more.
how to reference to an image in seeds.rb
Suppose you are saving your images under public/images
, Carrierwave requires that you pass an IO object to the Rails model, so to set it up correctly in the seeds.rb
file you instead need to do:
User.create!(
name: "Example User",
email: "example@railstutorial.org",
password: "foobar",
password_confirmation: "foobar",
admin: true,
politics: 'left',
car: true,
pets: 'I like horses and bears',
music: 'American country and folk',
picture: File.open(Rails.root.join('public', 'images', 'pic1.jpg')),
profile: 'I like music and the Ruby and Python programming languages',
activated: true,
activated_at: Time.zone.now
)
See that I've changed picture
to File.open(Rails.root.join('public', 'images', 'pic1.jpg'))
Related Topics
Ruby: How to Find the Key of the Largest Value in a Hash
How to Find If Range Is Contained in an Array of Ranges
Ruby on Rails 4 - Simple_Form Multiple Select Input
Testing Routes with Subdomain Constraints Using Rspec
Installing Ruby-2.1.2: Cannot Load Such File -- Openssl (Loaderror)
What Is the Purpose of 'Kernel'
Ruby: Array Contained in Array, Any Order
Changing Songs on Jplayer by Clicking a Link, Hosted on Amazon S3
Problem Using Openstruct with Erb
Remove Subdomain from String in Ruby
Rails: Methods Shared by Multiple Controllers
How to Model a Mutual Friendship in Rails
Mailchimp API Not Replacing Mc:Edit Content Sections (Using Ruby Library)
Select Checkbox Pass Array in Ruby on Rails
Ruby Variable Name with Double Underscores
How to Summarize Array of Integers as an Array of Ranges
How to Strip Leading and Trailing Quote from String, in Ruby