Attach s3 object to SendGrid Email - ruby-on-rails

I'd like to attach an image from s3 to a sendgrid email. Ideally there is no need to save the file on disk. How can I convert an object in s3 to a base64 encoded string?
file = s3.get_object(bucket: "my_bucket",
key: "key"
)
obj = {
content: file.body.read,
filename: "file_name"
}
Note that the file is a StringIO object. This code also throws the following error JSON::GeneratorError: source sequence is illegal/malformed utf-8
How can I convert an object in s3 to a base64 encoded string?

Related

Getting error "The attachment content must be base64 encoded" while sending pdf in zip as an attachment using SendGrid

We are using SendGrid latest available Java API to send emails. We are attaching a PDF enclosed in a zip file.
While sending mail we are getting a 404 response code and error message stating "The attachment content must be base64 encoded"
Complete Error Message:
{"errors":\[{"message":"The attachment content must be base64 encoded.","field":"attachments.0.content","help":"http://sendgrid.com/docs/API_Reference/Web_API_v3/Mail/errors.html#message.attachments.content"}\]}
What are we doing wrong? How can we solve this issue and send this attachment? Here is the code where we try to send the PDF in a Zip.
Code:
Path file = Paths.get(this.file.getAbsolutePath());
Attachments attachments = new Attachments();
attachments.setFilename(Base64.getMimeEncoder().encodeToString(file.getFileName().toString().getBytes(StandardCharsets.UTF_8)));
//attachments.setType``("application/pdf");
attachments.setDisposition("attachment");
byte[] attachmentContentBytes = Files.readAllBytes(file);
String attachmentContent = Base64.getMimeEncoder().encodeToString(attachmentContentBytes);
attachments.setContent(attachmentContent);
mail.addAttachments(attachments);
com.sendgrid.SendGrid sg = new com.sendgrid.SendGrid(this.apiKey);
Request request = new Request();
request.setMethod(Method.POST);
request.setEndpoint("mail/send");
request.setBody(mail.build());
Response response = sg.api(request);
Response:
{"errors":\[{"message":"The attachment content must be base64 encoded.","field":"attachments.0.content","help":"http://sendgrid.com/docs/API_Reference/Web_API_v3/Mail/errors.html#message.attachments.content"}\]}
Maven dependencies:
com.sendgrid.sendgrid-java 4.9.1
Try Base64.getEncoder() instead of Base64.getMimeEncoder(). Sometimes Sendgrid does not recognize the result from getMimeEncoder().

Do I have to download an image before upload it to s3?

I have Rails app with embedded images. What I want is to upload these images to s3 and serve theme from there instead of form original source Do I have to download the img to my server before upload it to s3?
Short answer: If you're scraping someone's content, then...yes, you need to pull the file down before uploading to to S3.
Long answer: If the other site (the original source) is working with you, you can give them a Presigned URL that they can use to upload to your S3 bucket.
From Amazon's docs: https://docs.aws.amazon.com/AmazonS3/latest/dev/UploadObjectPreSignedURLRubySDK.html
#Uploading an object using a presigned URL for SDK for Ruby - Version 3.
require 'aws-sdk-s3'
require 'net/http'
s3 = Aws::S3::Resource.new(region:'us-west-2')
obj = s3.bucket('BucketName').object('KeyName')
# Replace BucketName with the name of your bucket.
# Replace KeyName with the name of the object you are creating or replacing.
url = URI.parse(obj.presigned_url(:put))
body = "Hello World!"
# This is the contents of your object. In this case, it's a simple string.
Net::HTTP.start(url.host) do |http|
http.send_request("PUT", url.request_uri, body, {
# This is required, or Net::HTTP will add a default unsigned content-type.
"content-type" => "",
})
end
puts obj.get.body.read
# This will print out the contents of your object to the terminal window.

ruby encode a p12 certificate(binary) and send as a json response

I have a pem certificate with a private key.
I am using the above information to generate a p12 certificate which is password protected as follows:
def p12_cert
ca_cert = x509_cert(File.open("#{root}/ca-cert.crt").read)
p12 = OpenSSL::PKCS12.create(#random_pass, 'My Certificate',
rsa_pkey(private_key), x509_cert(public_cert), [ca_cert])
create_file('p12', p12.to_der, ':ASCII-8BIT')
end
The issue is this is in binary format and cannot be transmitted via a json API.
Can someone how me how to encode it(maybe base64) so that this can be sent as a JSON response?
EDIT: I opened the p12 file for read and then tried to base64 encode, got the following:
irb(main):017:0> enc_p12 = Base64.encode64(p12) TypeError: no implicit
conversion of OpenSSL::PKCS12 into String
You don't usually encode the PKCS12 object itself but the raw file. Something like
Base64.encode64( File.read(filename, mode: 'rb')

How to convert an array of bytes to JSON string in Ruby

What I am trying to achieve:
Convert a Dictionary to NSData which contains normal text as well as an image:
let payload: Dictionary<String, AnyObject> = [
"some_item": "some_value",
"img": UIImagePNGRepresentation(img)!
]
let data: NSData = NSKeyedArchiver.archivedDataWithRootObject(payload)
Send this data to the server using WebSocket writeData
Parse the array of bytes to get a JSON string and save the image and send back some response.
I am using Rails4 as the backend and I have tried pack but it doesn't work. I am not sure if this is doable or not.
I know Base64 encoding will work instead of byte data, but it's a bit slower than what I would prefer.
First you need to stop using NSKeyedArchiver and instead use NSJSONSerialization.Tl his will generate actual JSON data for you that you should be able to unpack easily on the server.
When using an image you either:
don't use JSON with it
convert the image data into base64 and create the JSON including that text
use multi-part form upload with a section for the image and another for the rest of the JSON

Decode base64 image in Grails [duplicate]

This question already has answers here:
Convert base64 string to image
(9 answers)
Closed 7 years ago.
I have a post api where I am sending a json string which contain the base64 encoded image.Below is the json string
{ "imageData":"base64encoded string",
"status":"1"
}
where base64encode string is iVBORw0KGgoAAAANSUhEUgAAAHgAAACgCAIAAABIaz/HAAAAAXNSR0IArs4c6QAA\r\nABxpRE9UAAAAAgAAAAAAAABQAAAAKAAAAFAAAABQAABWL3xrAqoAAEAASURBVHgB\r\nlL2Fe1t7mueZme6uewNGMUu2LNkyySSjDJKZmZkSO8zM7CTmmJnZYbxUVbdgsKp7\r\nqqdrdp
I cant post the complete encoding since its too lengthy. How can I convert this encoded string into a image file at server side.Actually from there I suppose to upload the image on a ftp server.
Base64 uses Ascii characters to send binary files, so to retrieve your image, you basically have to decode the Base64 string back to a byte array and save it to a file.
String encoded = 'iVBORw0KGgoAAAANSUhEUg' // You complete String
encoded.replaceAll("\r", "")
encoded.replaceAll("\n", "")
byte[] decoded = encoded.decodeBase64()
new File("file/path").withOutputStream {
it.write(decoded);
}
Edit: You problem of invalid charatercomes from the \r\n characters you have in the encoded String, you must have your base64 string in one line to decode it. I updated the sample code to do it.

Resources