Rails 3 Paperclip with file upload/downloads - ruby-on-rails

I have a rails 3 app that allows users to share files by uploading them to Amazon s3 via paperclip, and I want to allow others users to download these files. However, some sort of post-processing seems to be going on with this file somewhere between my app and Amazon s3.
Here's my code:
has_attached_file :attachment,
:storage => :s3, :s3_credentials => "#{RAILS_ROOT}/config/s3.yml",
:path => ':id/:style', :bucket => "test_development"
This works fine, however if I actually go to the amazon s3 developer tools the url for the file just seems to be: http://s3.amazonaws.com/test_development/1/original without the original name or type.
I then tried using something like this: [p.attachment.url(:original, false), p.attachment_file_name].join("/")
which yields: http://s3.amazonaws.com/test_development/1/original/test.pdf
However if I got to this url I get a cryptic xml error:
<Error>
<Code>NoSuchKey</Code>
<Message>The specified key does not exist.</Message>
<Key>1/original/About Downloads.pdf</Key>
<RequestId>7E5CC6A01CADF831</RequestId>
<HostId>
4ruFf0JtdalnaIE/SHUAqT8hVYEda9Ul6gxNmYTIAniw7piTN+Q16uKKCzi9yezl
</HostId>
</Error>
What am I doing wrong here? I just want to upload the file to s3 without any sort of processing then download again later..how should I go about doing this?
Thanks!

The :path option is is used as the full filename. Nothing is added, it's only interpolated. Try :path => ':id/:style/:basename.:extension'.
And when you change :path, you often have to change :url also.
More infos:
http://rdoc.info/github/thoughtbot/paperclip/master/Paperclip/Storage/S3
http://rdoc.info/github/thoughtbot/paperclip/master/Paperclip/Storage/Filesystem
http://rdoc.info/github/thoughtbot/paperclip/master/Paperclip/ClassMethods#has_attached_file-instance_method

Related

Rails Sitemap_generator using aws_fog configuration

I am using sitemap_generator gem with rails 6 on heroku. I am told the easiest way is to use an s3 on amazon and bridge with aws_fog.
The implementation is well documented on the gem side... but I am struggling to make sure the amazon config is correct.
I search a lot and couldn't find anything so I was hoping someone could help
I configure an s3 instance lets name it example and I add it to region US East(Ohio). This is all pretty simple.
The Properties tab... what should and shouldn't be selected? i select nothing.
The Permissions tab. I make public, although this feels wrong... the bucket is for a sitemap, so it should be public right?
I set up my region as per the doumentation
SitemapGenerator::Sitemap.default_host = "https://www.example.com"
SitemapGenerator::Sitemap.public_path = 'tmp/'
SitemapGenerator::Sitemap.sitemaps_host = "https://example.s3.amazonaws.com/"
SitemapGenerator::Sitemap.sitemaps_path = 'sitemaps/'
SitemapGenerator::Sitemap.adapter = SitemapGenerator::S3Adapter.new(fog_provider: 'AWS',
aws_access_key_id: Rails.application.credentials.aws[:access_key_id],
aws_secret_access_key: Rails.application.credentials.aws[:secret_access_key],
fog_region: 'us-east-2')
when i hit rake sitemap:refresh:no_ping on my local host I get :status_line => "HTTP/1.1 301 Moved Permanently\r\n"
I think maybe i need to add the sitemaps folder to the s3 instance, so i do but i still get the :status_line => "HTTP/1.1 301 Moved Permanently\r\n".
Any tips would be great...
I am also using sitemap-generator gem on my rails application (heroku hosted and rails 6). I have the following code inside config/sitemap.rb, before SitemapGenerator::Sitemap.create. I have configured it with aws-sdk-s3 gem and it goes like this:
require 'aws-sdk-s3'
SitemapGenerator::Sitemap.default_host = "https://www.example.com"
SitemapGenerator::Sitemap.sitemaps_host = 'https://example.s3.eu-west-2.amazonaws.com/'
SitemapGenerator::Sitemap.adapter = SitemapGenerator::AwsSdkAdapter.new(Rails.application.credentials.dig(:amazon, :s3, :bucket),
aws_access_key_id: Rails.application.credentials.dig(:amazon, :s3, :access_key_id),
aws_secret_access_key: Rails.application.credentials.dig(:amazon, :s3, :secret_access_key),
aws_region: Rails.application.credentials.dig(:amazon, :s3, :region)
)

How to properly setup Rails + Paperclip + AWS CDN + Heroku

It seems like I finally figured how to setup Rails + Paperclip + AWS CDN + Heroku.
Everything seems to be working. Both CSS and js files load from cdn, as well as images.
Unfortunately sharing functionality is broken. Open graph can't parse image url. I assume it's because links are in this format https:////drex16ydhdd8s.cloudfront.net/...rest_of_url
Originally, long time ago, I've configured CDN link to be //drex16ydhdd8s.cloudfront.net. I understand I need to remove slashes in front of the link, make it drex16ydhdd8s.cloudfront.net instead.
The problem is, if I do it, Heroku gives me Application Error. (displays their static page)
Logs don't display anything helpful, other than it seems it goes over memory limit pretty much immediately.
I've contacted Heroku support, but their response was
You should not need any slashes, it should just be a host name. (As seen in the documentation for config.action_controller.asset_host.)
If removing the slashes causes errors, you'll want to debug those errors.
I tried to do it locally, everything seems to work as expected.
environments/production.rb
config.action_controller.asset_host = ENV.fetch("ASSET_HOST", ENV.fetch("APPLICATION_HOST"))
config.paperclip_defaults = {
storage: :s3,
s3_protocol: :https,
s3_region: ENV["AWS_REGION"],
url: ":s3_alias_url",
path: "/:class/:attachment/:id_partition/:style/:filename",
s3_host_alias: ENV.fetch("ASSET_HOST"),
s3_credentials: {
bucket: ENV["S3_BUCKET_NAME"],
access_key_id: ENV["AWS_ACCESS_KEY_ID"],
secret_access_key: ENV["AWS_SECRET_ACCESS_KEY"]
},
default_url: "https://s3.amazonaws.com/ezpoisk/missing-small.png"
}
env variable
ASSET_HOST = //drex16ydhdd8s.cloudfront.net
on CDN I have 2 befaviors
/assets/* - that points to domain name
default (*) - that points to s3 bucket
Does anyone have any ideas?
Solution.
I had in production.rb
config.assets.compile = true
I'm not strong on details here, I just remember that I made a note on this line to possibly remove it when switching to cdn.
After digging through this answer I have decided to try it out. So I
removed the lined,
deployed,
all works fine.
Tried updating cdn link then.
At first, same issue persisted, url for some reason was /drex16ydhdd8s.cloudfront.net, but after few seconds it now seems
to be all good.

Getting Resource interpreted as Image but transferred with MIME type text/html

Just switched over to Refile for image uploads on my Rails application.
I have the uploads going directly to my s3 bucket. I have two buckets configured (with same settings), one for testing and one for production.
Everything in my local development works fine, and uploading to my bucket in production works, but on all the uploaded images I get the following when rendering them on a webpage.
Resource interpreted as Image but transferred with MIME type text/html:
Also in production, the images are not showing up.
I've looked into permissions for the buckets, but they seem to be good to go. I've also looked at others questions/answers regarding this warning, but have been unable to find any that pertain here.
If any code is needed please let me know.
config/initializers/refile.rb
require 'refile/backend/s3'
aws = {
access_key_id: Rails.application.secrets.aws['access_key_id'],
secret_access_key: Rails.application.secrets.aws['secret_access_key'],
bucket: Rails.application.secrets.aws['s3_bucket_name'],
use_ssl: true
}
Refile.cache = Refile::Backend::S3.new(max_size: 5.megabytes, prefix: 'cache', **aws)
Refile.store = Refile::Backend::S3.new(prefix: 'store', **aws)
Gist of the image helper
attachment_image_tag(avatar, :image, :fill, size, size)
Thanks for taking a look.

Rails and HTML5 Video MimeTypes Unsupported

I am working on a simple Rails app where I would like to play a video that is uploaded to the application. The video I am uploading is a h264/MP4 video, I have verified the codec. It's uploaded fine and I can watch the video in the browser if I go to the URL.
However, when trying to use HTML5 to display the video, on the page I get
Video format or MIME type is not supported
In my config/initializers/mime_types.rb file I have tried the following...
Mime::Type.register "video/mp4", :mp4
MIME::Types.add(MIME::Type.from_array("video/mp4", %(mp4)))
Taken from this question: Rails: MIME type issues with .m4v files
And I have also tried...
Rack::Mime::MIME_TYPES.merge!({
".ogg" => "application/ogg",
".ogx" => "application/ogg",
".ogv" => "video/ogg",
".oga" => "audio/ogg",
".mp4" => "video/mp4",
".m4v" => "video/mp4",
".mp3" => "audio/mpeg",
".m4a" => "audio/mpeg"
})
I remembered to restart my server after trying those different MIME initializers.
But neither seems to work. Any ideas?
EDIT: Also I should note when I run
curl -I http://localhost:3000/videos/SAMPLE.mp4 | grep Content-Type
I get back "Content-Type: video/mp4".
EDIT 2: Answer posted below.
Turns out everything I posted code-wise is fine. It was just a browser compatibility issue (MP4 on Firefox)...well, hopefully someone will find my misfortune useful!

What does this error mean in Rails: "Errno::ENOENT in AssetsController#get ...No such file or directory...."

Im writing an app to store files on Amazon S3. Im pretty close, Im able to save and retrieve files using a url. However since these links are public Im trying to use the following method in my assetscontroller to retrieve stored files from S3.
As links these files can be viewed/accessed in the browser, but if I use this code :
#This action will let the users download the files (after a simple authorization check)
def get
asset = current_user.assets.find_by_id(params[:id])
if asset
#Parse the URL for special characters first before downloading
data = open("#{URI.parse(URI.encode(asset.uploaded_file.url))}")
#then again, use the "send_data" method to send the above binary "data" as file.
send_data data, :filename => asset.uploaded_file_file_name
else
flash[:error]="Access Violation"
redirect_to assets_path
end
end
Im getting this error in my browser:
Errno::ENOENT in AssetsController#get
No such file or directory - http://s3.amazonaws.com/BUCKETNAME/assets/29/FILENAME.jpeg? 1339979591
When I click on the resource on the S3 site as Im logged into the S3 management console, the file is shown in my browser and its link is
https://s3.amazonaws.com/BUCKETNAME/assets/29/FILENAME.jpeg? AWSAccessKeyId=XXXXXXXXXXXExpires=1340003832&Signature=XXXXXXXXXXXXXXXXXX-amz-security- token=XXXXXXXXX//////////XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
So it does exist but cant be accessed through my app
Here is my Application Trace from my browser:
app/controllers/assets_controller.rb:99:in `initialize'
app/controllers/assets_controller.rb:99:in `open'
app/controllers/assets_controller.rb:99:in `get'
Any clues on whats going on?
Thanks
You can also just redirect the user to the file on S3.
Just try
redirect_to asset.uploaded_file.url
instead of send_file. send_file expects a path to a local file, which is then used by the webserver.
If you've set s3_permissions => :private, then you need to call
redirect_to asset.uploaded_file.expiring_url(10)
It's also interesting that in your error message it is http against https in s3 - you can also try to add the following option to your model's has_attached_file
:s3_protocol => 'https'
Hope this helps.

Resources