Upload Image via facebook marketing api through browser - ruby-on-rails

I am trying to use the Facebook marketing API SDK to upload images to Facebook.
This is the sdk
I want the user to be able to click to select a file from the browser and run the upload via Rails and the SDK.
Basically, here is the flow I am trying to do.
user select file
click upload
The backend controller processes the request and uploads it to facebook via the API.
However, the issue I am running into is, for security reasons, browsers do not have access to file path, which Facebook SDK asks for.
ad_account.adimages.create({
'logo1.png' => File.open('./assets/logo1.jpg')
})
If I use ActionDispatch::Http::FileUpload that is built into Rails or carrierwave, I get access to the tempfile, which has a name similar to RackMultipart20170803-89798-1e9hr
If I try to upload that to Facebook, I get an error saying
API does not accept files of this type
Does anyone have an idea on what the best option is? The only thing I can think of is upload the file to a host like cloudinary, then get the url from that and upload via the url from cloudinary.

You are right, a possible solution for your case is using Cloudinary.
Cloudinary's Ruby integration library is available as an open-source Ruby GEM.
To install the Cloudinary Ruby GEM, run:
gem install cloudinary
If you use Rails 3.x or higher, edit your Gemfile, add the following line and run bundle.
gem 'cloudinary'
Your cloud_name account parameter is required to build URLs for your media assets. api_key and api_secret are further needed to perform secure API calls to Cloudinary.
Setting the configuration parameters can be done either programmatically in each call to a Cloudinary method or globally using a cloudinary.yml configuration file, located under the config directory of your Rails project.
Here's an example of a cloudinary.yml file:
production:
cloud_name: "sample"
api_key: "874837483274837"
api_secret: "a676b67565c6767a6767d6767f676fe1"
Uploading directly from the browser is done using Cloudinary's jQuery plugin
http://cloudinary.com/documentation/jquery_integration
To ensure that all uploads were authorized by your application, a secure signature must first be generated in your server-side Rails code.
Full disclosure: I work as a software engineer at Cloudinary.

A solution I found is the create a duplicate copy of the uploaded files in the public folder and then process from there.
uploaded_file = params["file"]
file_name = uploaded_file.original_filename
file_path = File.expand_path(uploaded_file.tempfile.path)
file = File.open("#{FILE_PATH}/#{file_name}", "wb")
file.write uploaded_file.tempfile.read
file.close

Related

How to tweet a jpeg/mp4 with the twitter gem in Rails through ActiveStorage S3 uploads?

I am trying to Tweet from my Rails App (7.0.1), Ruby (3.0.2). I am using the "twitter" gem and others to connect the Twitter account and publish to Twitter. Everything works fine as long as I am Tweeting text only. The Text is from "Model.content".
There is another "Model.media" that is an attachment with "has_one_attached" which I want to use for the media upload to Twitter. It is stored in AWS S3.
This is the how to Tweet text using the gem (just "content" and not "Model.content" because I am tweeting from the Model.rb itself):
client.update(content)
It works and posts to Twitter fine.
To Tweet with media I can do it like that this according to the gem:
client.update_with_media(content, media)
The errors I am getting from the Rails logs are:
/Users/~/.rbenv/versions/3.0.2/lib/ruby/gems/3.0.0/gems/activesupport-7.0.1/lib/active_support/core_ext/module/delegation.rb:307:in `method_missing': undefined method `merge' for #<ActiveStorage::Attached::One:0x00007fca71579048 #name="media", #record=#<...">> (NoMethodError)
If I try this:
client.update_with_media(content, Rails.application.routes.url_helpers.rails_blob_path(media, only_path: true))
The errors I am getting from the Rails logs are (same happens for .jpeg):
/Users/~/.rbenv/versions/3.0.2/lib/ruby/gems/3.0.0/gems/twitter-7.0.0/lib/twitter/rest/upload_utils.rb:40:in `append_media': undefined method `eof?' for "/rails/active_storage/blobs/redirect/....mp4":String (NoMethodError)
I tried and looked for many solutions, they weren't specifically for this issue if I understand correctly. I feel I am missing a really small thing.
What is the best approach for this issue and how?
Links:
Gem link: https://rubygems.org/gems/twitter
Gem quick guide: https://github.com/sferik/twitter/blob/master/examples/Update.md#update
According to the docs, media must be either a File or an array of Files. This method doesn't support direct uploads so you have to download the file from S3 first and then upload it to twitter.
rails_blob_path returns a string and that's why it doesn't work. Also, this path is relative to your application domain, so you can't directly use it to reference files on your filesystem.
ActiveStorage has an open method that yields a Tempfile. Fortunately they behave just like regular Files so you should be able to pass it to update_with_media. You can use it like so:
media.open do |file|
client.update_with_media(content, file)
end
It will create a temporary file on the filesystem.
Alternatively, if your file is relatively small (which might not be the case with videos) you can use the download method. It will download the file and store it in memory:
client.update_with_media(content, media.download)
Side note: POST update_with_media is deprecated and shouldn't be used anymore.

Access to dropbox/google drive

In my ruby on rails application, I would like to be able to read (only read) files from a directory in my own dropbox.
All the tutorials I have found are to authorize access to the visitor's dropbox, and so require to login to dropbox using their oauth login page.
Is there a way to do it by using my credentials I'd save in a file in my application (and so without needing to log myself manually) ?
I'd also like to be able to do it from google drive.
Thanks !
I've followed the following steps and I've read/write to my Dropbox.
Title:
Using Dropbox with Ruby On Rails on Heroku
Objective:
Heroku does not offer a persist storage and suggests amazon s3 which needs a credit card to register and use it.
So Dropbox may be a good replacement at least for training and development level.
Steps:
1. Install sdk
command: gem install Dropbox-sdk
link: https://www.Dropbox.com/developers-v1/core/sdks/ruby
Create a Dropbox accout if you don't have one
link: https://www.Dropbox.com
action: create an account
Create an App on Dropbox platform
link: https://www.Dropbox.com/developers/apps
action: Specify a name for you app and you will given App Key and App Secret
remarks: App can have access to whole Dropbox or just a specific folder
Try this basic tutorial to test what you can do
link: https://www.Dropbox.com/developers-v1/core/start/ruby
action:
a.replace 'INSERT_APP_KEY' and 'INSERT_APP_SECRET' with your App keys
b.Execute ruby script
c.Browse given link to authorize and generate access token
d.Copy and paste the code on the script console and continue
caution:
The script is trying to load a local file first, so be sure you create it on proper path
Execution steps:
a.Authenticate
b.Upload file
c.Download file and write it to local
You could generate access token on your app home and use it instead of everytime generating it with APP_KEY & APP_SECRET
To Use Dropbox with rails (CarrierWare)
link: https://github.com/robin850/carrierwave-Dropbox
steps:
6a. include gem 'carrierwave-Dropbox' in your Gemfile
6b. run 'bundle install'
6c. run
rake Dropbox:authorize APP_KEY=app_key APP_SECRET=app_secret ACCESS_TYPE=Dropbox|app_folder
6d. set appropriate settings in your ImageUploader file (CustomNameUploader)
class ImageUploader < CarrierWave::Uploader::Base
storage :Dropbox
def initailize
CarrierWave.configure do |config|
...
# Dropbox settings
...
end
end
end
7. If your are on a source control it will be better choice to set values as env vars and then use them instead.
The link shows how to set or persist environment variables in ubuntu.
link: https://help.ubuntu.com/community/EnvironmentVariables
On production (heroku) set environment vars like follows:
usage: heroku config:set ACCESS_TOKEN_SECRET='your_app_access_token_secret'
link: https://devcenter.heroku.com/articles/config-vars
It will be a good practice to create carrierwave.rb file in config/initializers and place all setting in that file
also it can be set conditionally for production and development
Beware that Dropbox may be slow and you will get application error, so try it with smaller files and load them
with pagination if they are too many.
This is a published link on linkedin:
https://www.linkedin.com/pulse/using-dropbox-ruby-rails-heroku-serjik-isagholian?trk=prof-post

Upload file in Rails 3.2 app - develop engine or use gem?

We are looking to add a simple file uploader to our rails 3.2 app which is a business application (with Rails engines). Here are what we are looking for with the file uploader:
Allow access control to who can do what. For example, sales can upload a contract and acct can view the uploaded contract.
No change to current model. The file uploader acts on its own about file uploading, checking, storing and removing. We are thinking to have a file uploader engine and attach the engine to the Rails app.
File uploaded belongs to a model. For example, uploaded contract copy belongs to a project.
May need to upload file to a remote server.
We are evaluating options of developing our own uploader engine or find a upload gem such as carrierwave or paperclip. Can someone shed a light on rails file uploading and its related issue?
Using a combination of cancan and paperclip is a good option.

Upload File to AWS S3 with Rails

I have an external application uploading a file to my rails web app. (Developed on Heroku, but that's not completely relevant)
I need to upload that file to AWS. I've successfully connected to AWS with rails, but I can't figure out how to access the file that was uploaded.
I know I need to do File.open({path to file}), then pass the File to AWS
I forgot to set the multipart enctype in my test external application...if anyone else has this same problem this code should work:
AWS::S3::S3Object.store('{filename.ext_for_aws}',params[:{name_from_post}],'{bucket}')

Uploading to s3, using s3 servers

Does anyone have any sample code (preferrably in rails) that uploads to s3, using s3's servers.
Again, uploading directly to s3, where the actual upload/streaming is also preformed on amazon's servers.
Requirements:
Plupload, jQuery
Idea:
Authorize Upload via your app (sign it on server-side)
Use the signed request to upload the file to S3
Notify your app that the upload is done
Check whether S3 has received the file
I posted the code as a gist at https://gist.github.com/759939, it misses commments and you might run into some issues due to missing methods (had to rip it from our codebase).
stored_file.rb contains a model for your DB. Has many of paperclips helper methods inlined (which we used before we switched to direct upload to S3).
I hope you can use it as a sample to get your stuff running.
If you are using Rails 3, please check out my sample projects:
Sample project using Rails 3, Flash and MooTools-based FancyUploader to upload directly to S3: https://github.com/iwasrobbed/Rails3-S3-Uploader-FancyUploader
Sample project using Rails 3, Flash/Silverlight/GoogleGears/BrowserPlus and jQuery-based Plupload to upload directly to S3: https://github.com/iwasrobbed/Rails3-S3-Uploader-Plupload
To simply copy files, this is easy to use:
Smart Copy Script into S3
Amazon wrote a Ruby library for the S3 REST API. I haven't used it yet.
http://amazon.rubyforge.org/

Resources