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.
Related
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
This is my controller
Cotroller
def download
data = open(#attachment.file.url).read
#attachment.clicks = #attachment.clicks.to_i + 1
#attachment.save
send_data data, :type => #attachment.content_type, :filename => #attachment.name
end
example:
#attachment.file.url = "http://my_bucket.cloudfront.net/uploads/attachment/file/50/huge_file.pptx"
I did this, but if #attachement is a huge file (eg. 300MB), my server crash.
I want to allow users to download the file in the browser directly from my AWS server?
2) tip: Do you suggest to download file from S3 (where they are stored) or with CloudFront?
If you using carrierwave gem, you can try this to track number of clicks
def download
#attachment.clicks.to_i += 1
#attachment.save
redirect_to #attachment.file.url(query: {"response-content-disposition" => "attachment;"})
end
references:
Rails carrierwave S3 get url with Content-Disposition header
I have a Rails app on heroku. From the server side (using the REST API of InkFilepicker), I would like to convert a file, save it to my S3 bucket and store the S3 url to my model.
Concretely: Given an image (https://www.filepicker.io/api/file/hFHUCB3iTxyMzseuWOgG) I want to convert it (https://www.filepicker.io/api/file/hFHUCB3iTxyMzseuWOgG/convert?w=200&h=150&fit=clip) and store the converted image to my S3 bucket.
EDIT
Here is what I did at the end:
after_save :save_thumbnail_url_to_s3
def save_thumbnail_url_to_s3
convert_options = {
fit: 'clip',
h:500,
w:500
}
file = open("#{self.url}/convert?#{convert_options.to_query}")
# Writing file into S3 bucket
amazon = AWS::S3.new(access_key_id: ENV['AWS_ACCESS_KEY_ID'], secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'])
bucket = amazon.buckets[ENV['AWS_BUCKET']]
object = bucket.objects[s3_media_path]
written_file = object.write(file, acl: :public_read) # :authenticated_read
self.update_column :thumbnail_url, written_file.public_url.to_s
end
If you are using the filepicker.io API you can convert your file with the API and then provide then use open-uri as below to create a file stream that can be sent to S3, Tempfile as below behaves like the File API in ruby
[3] pry(main)> require 'open-uri'
=> true
[4] pry(main)> file = open("https://www.filepicker.io/api/file/hFHUCB3iTxyMzseuWOgG/convert?...")
=> #
[5] pry(main)> file.class
=> Tempfile
You can simply use the aws-s3 gem : https://github.com/marcel/aws-s3
But be careful, Heroku is read only oriented, you will only be able to work on temp files.
I don't know how to send data in xml format using an api.
http_post "https://crm.zoho.com/crm/private/xml/Notes/insertRecords?newFormat=1&authtoken=#{settings.api_token}&scope=crmapi&xmlData" do |req|
req.headers['Content-Type'] = 'application/xml'
req.body = {xmlData:{note:generate_note_content(ticket)}}.to_xml
end
Zoho's API requires that you POST the XML data.
Here is an example using the httparty gem:
require 'httparty'
class ZohoCRM
include HTTParty
end
# Generated rom Zoho API
AUTH_TOKEN = '1234567890ABCDEF'
# The contact (lead, etc.) record Id
entity_id = '1234567000000012345'
api_context = 'crmapi'
xml_data = "<Notes><row no='1'><FL val='entityId'>#{entity_id}</FL><FL val='Note Title'>Zoho CRM Sample Note</FL><FL val='Note Content'>This is sample content to test Zoho CRM API</FL></row></Notes>"
response = ZohoCRM.post(
'https://crm.zoho.com/crm/private/xml/Notes/insertRecords',
body: {
newFormat: '1',
authtoken: AUTH_TOKEN,
scope: api_context,
xmlData: xml_data
}
)
Cite: https://www.zoho.com/crm/help/api/insertrecords.html#Insert_notes_and_relate_to_the_primary_module
You should try using Net/http lib.
http://ruby-doc.org/stdlib-2.0.0/libdoc/net/http/rdoc/Net/HTTP/Post.html
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.