Upload multiple files using Faraday - ruby-on-rails

I'm trying to send a file array using Faraday with Rails. But when I send the files they arrive empty at the service that receives the files. Sending a single file works fine but with a array it doesn't. This is an example:
def attachment
if #transaction.product_id == ViewTransaction::MINI
return [Faraday::FilePart.new(File.open(CreatePdfAction.new(#transaction,'tickets').execute),
'application/pdf',
File.basename("Ticket")),
Faraday::FilePart.new(File.open(CreatePdfAction.new(#transaction,'vouchers').execute),
'application/pdf',
File.basename("Voucher"))]
else
return Faraday::FilePart.new(File.open(File.open(CreatePdfAction.new(#transaction,'vouchers').execute),
'application/pdf',
File.basename(template))
end
def payload(payload = {})
payload[:attachment] = attachment
payload[:data] = data
payload
end
a this execute the http post
conn = Faraday.new() do |f|
f.request :multipart
f.adapter :net_http
end
response = conn.post("http://email-service/v1/email", payload)

I don't recommend using faraday for upload file!
I'd recommend using paperclip package or this link:
https://guides.rubyonrails.org/active_storage_overview.html

Related

How to relay EWS email attachments to a REST endpoint using Viewpoint

I need to forward an Outlook EWS email and its attachments to a Rails server.
The attachments I am getting with the Viewpoint gem are returned as Viewpoint::EWS::Types::FileAttachment objects.
How can I pass these attachments to a Rails server using the rest-client library?
I managed to upload the files by using a StringIO and giving it a :path
# email is a Viewpoint::EWS::Types::Message
# email_endpoint is a RestClient::Resource
attachments = email.attachments.map do |attachment|
file = StringIO.new(Base64.decode64(attachment.content))
file.class.class_eval { attr_accessor :original_filename, :content_type, :path }
file.original_filename = attachment.file_name
file.content_type = attachment.content_type
file
end
response = email_endpoint.post(
email: {
subject: email.subject,
attachments: attachments
}
)
The rest-client library will automatically handle objects that respond to :path and :read as Files and use a multi-part upload.
Each attachment then shows up in Rails as an ActionDispatch::Http::UploadedFile with the correct filename.

Rails - Sending image using Faraday

I'm trying to make a request to an API sending an image and some other data, and getting the response. That's my code:
file = "assets/images/test.jpg"
conn = Faraday.new(:url => "api_url" ) do |faraday|
faraday.request :multipart
end
payload = { :profile_pic => Faraday::UploadIO.new(file, 'image/jpeg') }
conn.post "/test", payload
My first problem is that I'm always getting the following error:
Errno::ENOENT (No such file or directory - assets/images/test.png)
I've tried all the paths I could imagine. Where should be saved the image in directories to be found by Faraday?
The second question is about the response, how can I get the response and handle it?
The third one is that, I haven't understand what's the utility of the first parameter of the last call:
conn.post "/hello", payload
I've written "/hello" but don't have any idea about what's the real usage.
And the last one. Could I send a raw image saved in a variable instead of sending a path to Faraday?
EDIT
Now it's working, this is the solution:
Be aware that url must be only until .com, the rest of the path must go on conn.post like this example /v1/search.
c.adapter :net_http was needed too.
Message response is correctly handled in json variable.
Solution:
url = 'http://url.com'
file = Rails.root.to_s + "/app/assets/images/test.jpg"
conn = Faraday.new(:url => url ) do |c|
c.request :multipart
c.adapter :net_http
end
payload = { :image => Faraday::UploadIO.new(file, 'image/jpeg'), :token => token}
response = conn.post '/v1/search', payload
json = JSON.parse response.body
You should try this for your first question :
file = Rails.root.to_s + "/app/assets/images/test.jpg"
For your third question, the first parameters allows you to construct the right URL from the base "api_url". Please see the example from the Readme.
## POST ##
conn.post '/nigiri', { :name => 'Maguro' } # POST "name=maguro" to http://sushi.com/nigiri

Posting JSON with file content on Ruby / Rails

Does anyone know how to post a JSON to a Rails server with a file attached? Would the content be base64 encoded? Multipart? I honestly have no idea and havent really found anything here to help. Idea is to have a client posting a JSON to a rails API with the file attached, as well as having the Rails (with paperclip would be perfect) getting the JSON and saving the file properly. Thanks in advance
Here is how I solved this problem. First I created a rake task to upload the file within the json content:
desc "Tests JSON uploads with attached files on multipart formats"
task :picture => :environment do
file = File.open(Rails.root.join('lib', 'assets', 'photo.jpg'))
data = {title: "Something", description: "Else", file_content: Base64.encode64(file.read)}.to_json
req = Net::HTTP::Post.new("/users.json", {"Content-Type" => "application/json", 'Accept' => '*/*'})
req.body = data
response = Net::HTTP.new("localhost", "3000").start {|http| http.request(req) }
puts response.body
end
And then got this on the controller/model of my rails app, like this:
params[:user] = JSON.parse(request.body.read)
...
class User < ActiveRecord::Base
...
has_attached_file :picture, formats: {medium: "300x300#", thumb: "100#100"}
def file_content=(c)
filename = "#{Time.now.to_f.to_s.gsub('.', '_')}.jpg"
File.open("/tmp/#{filename}", 'wb') {|f| f.write(Base64.decode64(c).strip) }
self.picture = File.open("/tmp/#{filename}", 'r')
end
end
JSON is a data serializing format. There is no standard pattern for uploading data or files as data in the serialized object. JSON has expectations that the data fields will be basic objects so you probably want to use Base64 encoding of the file to turn it into a string.
You are free to define your structure however you want, and processing it is your responsibility.

How to handle csv download prompt through a post request in Rails

I have a servlet (java) returning a csv file. So in my controller I send a post request,
def handleCsvRequest
response = RestClient.post theUrlPathTotheServlet queryParams
end
Now how do I handle the response so that it prompts the user to download this csv file. I know you can do this via a form and hidden Iframe but i'd like to do it through rails. I am looking through fastercsv but i am not finding great examples. Many thanks.
I have tried the following:
i have tried the following
csv_string = RestClient.post url, json, :content_type => :json
csv_file = CSV.generate do |csv|
csv << [csv_string]
end
send_data csv_file, :type => 'text/csv; charset=iso-8859-1; header=present', :disposition => "attachment; filename=report.csv"
but i don't get prompt for a file download? any ideas?
Do have a look at
1> http://fastercsv.rubyforge.org/ - For Documenation
2> http://supriya-surve.blogspot.com/2010/02/using-fastercsv-to-import-data.html - As an e.g.
Use send_file or send_data to send the csv data back to the browser.
A typical example of send_data is something along the lines:
csv_data = CSV.generate do
# block to generate CSV text
end
send_data csv_data, :filename => 'your_data.csv'
A typical example of send_file is
#csv_filename ="#{RAILS_ROOT}/tmp/your_data.csv"
send_file #csv_filename, :filename => "your_data.csv"
This should work in development. If this does not work in production, and you are using an Apache server,
you have to comment out the following line in config/environments/production.rb
config.action_dispatch.x_sendfile_header = "X-Sendfile"
Hope this helps.

Rails: How to to download a file from a http and save it into database

i would like to create a Rails controller that download a serie of jpg files from the web and directly write them into database as binary
(I am not trying to do an upload form)
Any clue on the way to do that ?
Thank you
Edit :
Here is some code I already wrote using attachment-fu gem :
http = Net::HTTP.new('awebsite', 443)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
http.start() { |http|
req = Net::HTTP::Get.new("image.jpg")
req.basic_auth login, password
response = http.request(req)
attachment = Attachment.new(:uploaded_data => response.body)
attachement.save
}
And I get an "undefined method `content_type' for #" error
Use open-url (in the Ruby stdlib) to grab the files, then use a gem like paperclip to store them in the db as attachments to your models.
UPDATE:
Attachment_fu does not accept the raw bytes, it needs a "file-like" object. Use this example of a LocalFile along with the code below to dump the image into a temp file then send that to your model.
http = Net::HTTP.new('www.google.com')
http.start() { |http|
req = Net::HTTP::Get.new("/intl/en_ALL/images/srpr/logo1w.png")
response = http.request(req)
tempfile = Tempfile.new('logo1w.png')
File.open(tempfile.path,'w') do |f|
f.write response.body
end
attachment = Attachment.new(:uploaded_data => LocalFile.new(tempfile.path))
attachement.save
}

Resources