Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Showing images with carrierwave in rails 3.1 in a private store folder

I have a rails 3.1 app and I am adding carrierwave to store images. But I want to store those images outside the public folde,r because they should only be accessible when users are loaded in the app. So I changed the store_dir in carrerwave with the initializer file:

CarrierWave.configure do |config|
  config.root = Rails.root
end

And my carrierwave uploader goes like this:

class ImageUploader < CarrierWave::Uploader::Base
...
def store_dir
  "imagenes_expedientes/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end

Images are stored correctly and if I use the public folder everything works fine. However when trying to move things to the private folder, images are not displayed and when I try to open them in a new window I get the following error:

Routing Error

No route matches [GET] "/imagenes_expedientes/volunteer/avatar/15/avatar.jpg"

I was trying to deliver the files using send_file through the controller, but instead of loading the page I only get the image downloaded.

  def show
    send_file "#{Rails.root}/imagenes_expedientes/avatar.jpg", :type=>"application/jpg", :x_sendfile=>true
  end

Finally Images are displayed like this in the views:

<%= image_tag(@volunteer.avatar_url, :alt => "Avatar", :class => "avatar round") if @volunteer.avatar? %>

This may probably be solved rather easy, but since I am somehow new to Rails, I don´t know what to do it. Should I set a route? Or is there anyway to display the images using the send_file method?

Thanks!

ANSWER

I managed to display images using x-sendfile and putting :disposition => 'inline' as suggested by clyfe. I made a new action in my controller:

  def image
    @volunteer = Volunteer.find(params[:id])
    send_file "#{Rails.root}/imagenes_expedientes/#{@volunteer.avatar_url}",:disposition => 'inline', :type=>"application/jpg", :x_sendfile=>true
  end

Added to the routes:

  resources :volunteers do
    member do
      get 'image'
    end 
  end

And displayed in the views:

<%= image_tag(image_volunteer_path(@volunteer), :alt => "Avatar", :class => "avatar round") if @volunteer.avatar? %>

Hope it helps others!

like image 536
reves Avatar asked Nov 11 '11 05:11

reves


People also ask

How do I add carrierwave to my Rails application?

The first gem is for CarrierWave, and the second gem called mini_magick helps with the resizing of images in your Rails application. With that done, run bundle install. Generate a scaffold resource to add CarrierWave’s functionality. Run the following command from your terminal:

What is the best way to send an image in rails?

The first one is the worst idea as it sends the entire image as plain text. While the later one multipart is preferable way to send file as it send the image data byte by byte. In Rails, we have few prominent gem Carrierwave , Paperclip , Dragonfly, etc, to implement this concept.

How many times does carrierwave copy an uploaded file?

By default, CarrierWave copies an uploaded file twice, first copying the file into the cache, then copying the file into the store. For large files, this can be prohibitively time consuming.

Why do we use carrier W Ave in rails?

We go with Carrier w ave as it simple and flexible to configure and include in Rails. It has a lot more flexibility and it doesn’t clutter your models with configuration.You can define uploader classes instead. It allows you to easily reuse, extend etc your upload configuration.


1 Answers

:disposition => 'inline' will make your images display in the browser instead of popping up the download dialog.

def show
  send_file "#{Rails.root}/imagenes_expedientes/avatar.jpg", :disposition => 'inline', :type=>"application/jpg", :x_sendfile=>true
end

Depending on the images sizes and the number of users you might want to move this action to a metal app, or a separate so as to not block the server.

like image 111
clyfe Avatar answered Oct 20 '22 00:10

clyfe