I am using carrierwave fog-google configuration for file download and upload to GCS bucket. However, my concern is I wanted to have a signed URL returned from GCS response with some expiration time.
Is there any configuration I need to set which would help me in receiving a response from GCS which will have signed URL and will expire let say after an hour?
class TestUploader < CarrierWave::Uploader::Base
storage :fog
def fog_credentials
{
:provider => 'google',
:google_project =>'my project',
:google_json_key_location =>'myCredentialFile.json'
}
end
def fog_provider
'fog/google'
end
def fog_directory
'{#bucket-name}'
end
def store_dir
when :File
"#{file.getpath}/file"
when :audio
"#{file.getpath}/audio"
else
p " Invalid file "
end
end
end
I tried to follow the 'Secure Upload' in carrier wave which is a bit confusing because I have customized the file path and all a bit. When I try to run the app, I get 'Cannot read file' error.
Here's the route :
match "/upload_files/:tenant_id/:model/:mount_as/:id/:basename.:extension" => "documents#download",via: [:get, :post]
class ImageUploader < CarrierWave::Uploader::Base
def store_dir
"upload_files/#{model.tenant_id}/#model.class.to_s.underscore}/#mounted_as}/#{model.id}"
end
end
carrierwave.rb initializer :
CarrierWave.configure do |config|
config.permissions = 0600
config.directory_permissions = 0700
config.root = Rails.root
end
documents controller:`
def download
path = request.fullpath
send_file path
end
got the error
ActionController::MissingFile in DocumentsController#download
Cannot read file /upload_files/1/hoshin_attachment/image/3/support3_HoshinUserStatusReports_08_14_2015.pdf
Please help me to find the solution
CarrierWave seems to compute paths using a root variable and the uploader store_dir.
I wanted to store my files in a private folder under Rails.root.
To setup the root:
# config/initializers/carrierwave.rb
# Uploader settings
CarrierWave.root = Rails.root.to_s
CarrierWave::Uploader::Base.root = Rails.root.to_s
To setup the store_dir:
# In your uploader class definition
def store_dir
"private/your_app/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
Since files are not longer in the public folder, they require actions in controller to show and download. Lets assume the column for the uploaded file is named uploaded_file:
# In some controller
# you have to ensure #document initialize with a before_action filter
def show_file
send_file #document.unsigned_file.path,
filename: #document.uploaded_file_identifier,
disposition: :inline,
type: #document.uploaded_file.content_type
end
def download_file
send_file #document.unsigned_file.path,
filename: #document.uploaded_file_identifier,
disposition: :attachment,
type: #document.uploaded_file.content_type
end
This question already has answers here:
carrierwave - rails 3.1- undefined method: image_will_change
(5 answers)
Closed 8 years ago.
I have never seen this error before, undefined method 'attachment_will_change!' for #<Movie:0x00000106b16000>
Possibly something to do with carrierwave.
Params in movie model.
def movie_params
params.require(:movie).permit(:title, :rating, :total_gross, :attachment)
end
carrierwave.rb in initializers.
CarrierWave.configure do |config|
config.fog_credentials = {
:provider => 'abc', # required
:aws_access_key_id => 'abcabc', # required
:aws_secret_access_key => 'abcabcabc', # required
}
config.fog_directory = 'abcabc' # required
config.fog_public = false # optional, defaults to true
config.fog_attributes = {'Cache-Control'=>'max-age=315576000'} # optional, defaults to {}
end
imageuploader
include CarrierWave::MiniMagick
storage :fog
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
version :thumb do
process :resize_to_fit => [50, 50]
end
def extension_white_list
%w(jpg jpeg gif png)
end
end
As i said,you are missing attachment attribute in your movies table.You have to add attachment column in order to fix that error.
undefined method 'attachment_will_change!'
Generate a migration file by the following command
rails g migration AddAttachementToMovies attachement:string
It will generate a migration file something like this
class AddAttachmentToMovies < ActiveRecord::Migration
def change
add_column :movies, :attachment, :string
end
end
And then do rake db:migrate
Source
I just switched from storing my images uploaded via Carrierwave locally to using Amazon s3 via the fog gem in my Rails 3.1 app. While images are being added, when I click on an image in my application, the URL is providing my access key and a signature. Here is a sample URL (XXX replaced the string with the info):
https://s3.amazonaws.com/bucketname/uploads/photo/image/2/IMG_4842.jpg?AWSAccessKeyId=XXX&Signature=XXX%3D&Expires=1332093418
This is happening in development (localhost:3000) and when I am using heroku for production. Here is my uploader:
class ImageUploader < CarrierWave::Uploader::Base
include CarrierWave::RMagick
storage :fog
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
process :convert => :jpg
process :resize_to_limit => [640, 640]
version :thumb do
process :convert => :jpg
process :resize_to_fill => [280, 205]
end
version :avatar do
process :convert => :jpg
process :resize_to_fill => [120, 120]
end
end
And my config/initializers/fog.rb :
CarrierWave.configure do |config|
config.fog_credentials = {
:provider => 'AWS',
:aws_access_key_id => 'XXX',
:aws_secret_access_key => 'XXX',
}
config.fog_directory = 'bucketname'
config.fog_public = false
end
Anyone know how to make sure this information isn't available?
UPDATE: Adding view and controller code:
from a partial in users/show.html.erb:
<% if #user.photos.any? %>
<% for photo in #user.photos %>
<li class="span4 hidey">
<div class="thumb_box">
<%=link_to(image_tag(photo.image_url(:thumb).to_s), photo.image_url.to_s,
:class=>"lb_test") %>
...
</div>
</li>
<% end %>
<% end %>
users_controller.rb:
def show
#user = User.find(params[:id])
end
UPDATE: Adding an error page I get when removing the access key information from the url:
This XML file does not appear to have any style information associated with it. The document tree is shown below.
<Error>
<Code>AccessDenied</Code>
<Message>Access Denied</Message>
<RequestId>47077D6EC13AD1D8</RequestId>
<HostId>+HTeODcWTqv3gbRIAwf+lI6sPzfNTegDXjT9SnMdqrYr7gLD1TD0qN+OgMLwA1JO
</HostId>
</Error>
Remove
config.fog_public = false
That's a non-default value :)
What you are seeing is a signed-url. Without the full url (including key,signature,expires), you'll get an access denied. It is working exactly as it should. And I am guessing the key is just a public key, that is useless without your private key (which AWS has).
Try photo.image.url instead of photo.image_url. That's what I'm using.
been trying to search the reason for this error for a long time and can't seem to find any...
So I have a rails app, and I utilize carrierwave for pictures uploading. I also want to utilize Amazon S3 for file upload storage in my app.
Initially as I am developing the app I allowed file uploads to be on the on :file, i.e.
image_uploader.rb
# Choose what kind of storage to use for this uploader:
storage :file
# storage :fog
Now upon finishing up development and placing it live (I use heroku), I decided to change the carrierwave storage to S3 to test it locally.
image_uploader.rb
# Choose what kind of storage to use for this uploader:
# storage :file
storage :fog
However, now when I try to upload a picture (be it for user avatar, etc) I get this error:
Excon::Errors::Forbidden in UsersController#update
Expected(200) <=> Actual(403 Forbidden)
request => {:connect_timeout=>60, :headers=>{"Content-Length"=>74577, "x-amz- acl"=>"private", "Content-Type"=>"image/png", "Date"=>"Sun, 26 Feb 2012 10:00:43 +0000", "Authorization"=>"AWS AKIAJOCDPFOU7UTT4HOQ:8ZnOy7X71nQAM87yraSI24Y5bSw=", "Host"=>"s3.amazonaws.com:443"}, :instrumentor_name=>"excon", :mock=>false, :read_timeout=>60, :retry_limit=>4, :ssl_verify_peer=>true, :write_timeout=>60, :host=>"s3.amazonaws.com", :path=>"/uploads//uploads%2Fuser%2Favatar%2F1%2Fjeffportraitmedium.png", :port=>"443", :query=>nil, :scheme=>"https", :body=>"\x89PNG\r\n\x1A\n\x00\x00\x00\rIHDR\x00\x00\x00\xC2\x00\x00\x00\xC3\b\x06\x00\x00\x00\xD0\xBD\xCE\x94\x00\x00\nCiCCPICC Profile\x00\x00x\x01\x9D\x96wTSY\x13\xC0\xEF{/\xBD\xD0\x12B\x91\x12z\rMJ\x00\x91\x12z\x91^E%$\
...
# The code you see above to the far right repeats itself a LOT
...
1#\x85\xB5\t\xFC_y~\xA6=:\xB2\xD0^\xBB~i\xBB\x82\x8F\x9B\xAF\xE7\x04m\xB2i\xFF\x17O\x94S\xF7l\x87\xA8&\x00\x00\x00\x00IEND\xAEB`\x82", :expects=>200, :idempotent=>true, :method=>"PUT"}
response => #<Excon::Response:0x007fc88ca9f3d8 #body="<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Error><Code>AccessDenied</Code><Message>Access Denied</Message><RequestId>8EFA56C0DDDC8878</RequestId><HostId>1OxWXppSSUq1MFjQwvnFptuCM3gKOuKdlQQyVSEgvzzv4Aj+r2hSFM2UUw2NYyrR</HostId></Error>", #headers={"x-amz-request-id"=>"8EFA56C0DDDC8878", "x-amz-id-2"=>"1OxWXppSSUq1MFjQwvnFptuCM3gKOuKdlQQyVSEgvzzv4Aj+r2hSFM2UUw2NYyrR", "Content-Type"=>"application/xml", "Transfer-Encoding"=>"chunked", "Date"=>"Sun, 26 Feb 2012 10:00:47 GMT", "Connection"=>"close", "Server"=>"AmazonS3"}, #status=403>
And then it says this as well for my application trace:
app/controllers/users_controller.rb:39:in `update'
And my REQUEST parameters:
{"utf8"=>"✓",
"_method"=>"put",
"authenticity_token"=>"DvADD1vYpCLcghq+EIOwVSjsfmAWCHhtA3VI5VGD/q8=",
"user"=>{"avatar"=>#<ActionDispatch::Http::UploadedFile:0x007fc88cde76f8
#original_filename="JeffPortraitMedium.png",
#content_type="image/png",
#headers="Content-Disposition: form-data; name=\"user[avatar]\";
filename=\"JeffPortraitMedium.png\"\r\nContent-Type: image/png\r\n",
#tempfile=#<File:/var/folders/vg/98nv58ss4v7gcbf8px_8dyqc0000gq/T/RackMultipart20120226- 19096-1ppu2sr>>,
"remote_avatar_url"=>"",
"name"=>"Jeff Lam ",
"email"=>"email#gmail.com",
"user_bio"=>"Tester Hello",
"shop"=>"1"},
"commit"=>"Update Changes",
"id"=>"1"}
Here's my users_controller.rb partial code:
def update
#user = User.find(params[:id])
if #user.update_attributes(params[:user])
redirect_back_or root_path
flash[:success] = "Your have updated your settings successfully."
else
flash.now[:error] = "Sorry! We are unable to update your settings. Please check your fields and try again."
render 'edit'
end
end
My image_uploader.rb code
# encoding: utf-8
class ImageUploader < CarrierWave::Uploader::Base
# Include RMagick or MiniMagick support:
# include CarrierWave::RMagick
include CarrierWave::MiniMagick
# Choose what kind of storage to use for this uploader:
# storage :file
storage :fog
# Override the directory where uploaded files will be stored.
# This is a sensible default for uploaders that are meant to be mounted:
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
# Provide a default URL as a default if there hasn't been a file uploaded:
# def default_url
# "/images/fallback/" + [version_name, "default.png"].compact.join('_')
# end
# Process files as they are uploaded:
# process :scale => [200, 300]
#
# def scale(width, height)
# # do something
# end
# Create different versions of your uploaded files:
version :thumb do
process resize_to_fill: [360, 250]
end
version :cover_photo_thumb do
process resize_to_fill: [1170, 400]
end
version :event do
process resize_to_fill: [550, 382]
end
version :product do
process resize_to_fit: [226, 316]
end
# Add a white list of extensions which are allowed to be uploaded.
# For images you might use something like this:
def extension_white_list
%w(jpg jpeg gif png)
end
# Override the filename of the uploaded files:
# Avoid using model.id or version_name here, see uploader/store.rb for details.
# def filename
# "something.jpg" if original_filename
# end
# fix for Heroku, unfortunately, it disables caching,
# see: https://github.com/jnicklas/carrierwave/wiki/How-to%3A-Make-Carrierwave-work-on-Heroku
def cache_dir
"#{Rails.root}/tmp/uploads"
end
end
Finally, my fog.rb file in the config/initializers
CarrierWave.configure do |config|
config.fog_credentials = {
:provider => 'AWS', # required
:aws_access_key_id => 'ACCESS_KEY', # required
:aws_secret_access_key => 'SECRET_ACCESS_KEY/ZN5SkOUtOEHd61/Cglq9', # required
:region => 'Singapore' # optional, defaults to 'us-east-1'
}
config.fog_directory = 'ruuva/' # required
config.fog_public = false # optional, defaults to true
end
I'm actually quite confused on some of the things in my fog.rb. Firstly, should I change my region to Singapore if I created a bucket called "ruuva", with region "Singapore" on my amazon s3 account?
Thank you to anyone that can help in advance!
First make sure you use the right credentials by not setting custom region and custom directory (create a fake bucket for free in the default region)
Then I think you are not using the right name for the region. Try setting your region like this:
:region => 'ap-southeast-1'
We were facing the same problem and fixed that changing the user's permission associated to your access key, changing it to "Power User". Check if you need your user to be power user before put it into productions.