Reputation: 4287
My client app is an iOS app written in Swift. In that iOS app, I convert an image to a Base64 encoded String and then send this String to my Rails server in the body of an HTTP request. This is my code for doing so:
// Create a new URL request with the URL
let request: NSMutableURLRequest = NSMutableURLRequest(URL: url)
// Set the HTTP method to POST
request.HTTPMethod = "POST"
// Set the content type of the request to XML
request.setValue("application/xml", forHTTPHeaderField: "Content-Type")
// Convert the image to binary and then to a Base 64 Encoded String
let imageData:String = UIImagePNGRepresentation(image).base64EncodedStringWithOptions(nil)
// Set the HTTP Body of the request to the image
request.HTTPBody = NSData(base64EncodedString: imageData, options: nil)
In my Rails controller handling the request, I would like to retrieve the image and send it as an email attachment. I do NOT want to save the image anywhere; I just want to decode the image in memory and then somehow use that as the email attachment.
How can I retrieve the image data in my Rails controller and decode it in a way that would allow me to send it back as an email attachment?
To retrieve the image data, I've tried using request.body.read
, but this returns an empty String for some reason.
Thanks in advance for any help!
EDIT:
request.body.read
was returning an empty String because I used a GET request. I've since learned that it's not a good idea to send an HTTP Body in a GET request, so I changed the method to POST. Now request.body.read
is returning my encoded String! I've also added the Content-Type header to the request.
Still, I can't figure out how to properly decode the HTTP Body and assign it to an image object of some sort.
EDIT #2:
I've managed to send the email attachment in my mailer using the following code:
attachments["file.png"] =
{
mime_type: 'image/png',
content: Base64.decode64(request.body.read)
}
Unfortunately, the PNG file cannot be opened when I receive it in the email. I don't know if the encoding translates well from Swift to Ruby. I'll keep investigating.
EDIT #3:
I removed the Base64 String encoding, and it's working great! See my posted answer below.
Upvotes: 1
Views: 1373
Reputation: 4287
I figured it out! I think the Base64 encoding/decoding isn't performed the same way on Swift and Ruby, so I decided to send the image as NSData without String encoding and then send it back, and that worked! Here is my final code:
Swift
// Create a URL
let url:NSURL = NSURL(string: urlString)!
// Create a new URL request with the URL
let request: NSMutableURLRequest = NSMutableURLRequest(URL: url)
// Set the HTTP method to POST
// GET requests usually do not have an HTTP Body, and it's considered a very bad idea to include one in a GET request
request.HTTPMethod = "POST"
// Set the content type of the request to XML
request.setValue("application/xml", forHTTPHeaderField: "Content-Type")
// Convert the image to binary data
let imageData:NSData = UIImagePNGRepresentation(image)
// Set the HTTP Body of the request to the image
request.HTTPBody = imageData
// Create a new queue
let queue:NSOperationQueue = NSOperationQueue()
// Send the async request
NSURLConnection.sendAsynchronousRequest(request, queue: queue, completionHandler:
{ (response:NSURLResponse!, data:NSData!, error:NSError!) -> Void in
println(response)
})
You can put this code in any method.
Ruby on Rails (Ruby 2.1.1 and Rails 4.2.0)
class ImageApiController < ApplicationController
# Skip verifying the authenticity token since a form wasn't submitted; a web request was sent
skip_before_filter :verify_authenticity_token, :only => [ :index ]
def index
params[:image] = request.body.read
# Send the email
UserMailer.image_attachment_email(params).deliver_now
respond_to do |format|
format.html
format.js { render plain: "Test" }
format.xml { render plain: "Test" }
end
end
end
Then in UserMailer:
class UserMailer < ApplicationMailer
def image_attachment_email(params)
attachments["image.png"] =
{
mime_type: 'image/png',
content: params[:image]
}
# Send an email
mail(to: "[email protected]", subject: "Image")
end
end
So actually no Base64 String encoding was needed. This code works great!
Upvotes: 3