views:

2555

answers:

5

Hello there,

I am currently putting together a rails-based web application which will only serve and receive data via json and xml. However, some requirements contain the ability to upload binary data (images).

Now to my understanding JSON is not entirely meant for that... but how do you in general tackle the problem of receiving binary files/data over those two entrypoints to your application?

Cheers and thanks, -Joerg

+2  A: 

I suggest encoding the binary data in something like base64. This would make it safe to use in XML or JSON format.

http://en.wikipedia.org/wiki/Base64

Stephen Cox
+1 Base 64 is the way to go
Robert Gould
+3  A: 

Hello,

maybe you could have a look on Base64 algorithm. This is used to "transform" everything to ascii char. You can code and decode it. It's used for webservices, or even on dotnet Serialization.

Hope this helps a little.

Edit: I saw "new post", while posting, someone was faster.Rails base64

Aif
A: 

Ohhh right... didn't think about that.. but nice! I'll give it a try, thanks!!

Jörg B.
A: 

If you are using Rails and json and xml than you are using HTTP. "POST" is a part of HTTP and is the best way to transform binary data. Base64 is a very inefficient way of doing this.

If your server is sending data, I would recommend putting a path to the file on the server in the XML or JSON. That way your server doesn't have to base64 encode the data and your client, which already supports HTTP GET, can pull down the data without decoding it. (GET /path/to/file)

For sending files, have your server and/or client generate a unique file name and use a two step process; the client will send the xml or json message with fileToBeUploaded: "name of file.ext" and after sending the message will POST the data with the aforementioned filename. Again, client and server won't have to encode and decode the data. This can be done with one request using a multi-part request.

Base64 is easy but will quickly chew up CPU and/or memory depending on the size of the data and frequency of requests. On the server-side, it's also not an operation which is cached whereas the operation of your web server reading the file from disk is.

nessence
+1  A: 

If your images are not too large, putting them in the database with a RoR :binary type makes a lot of sense. If you have database replicas, the images get copied for free to the other sites, there's no concern about orphaned or widowed images, and the atomic transaction issues become far simpler.

On the other hand, Nessence is right that Base64, as with any encoding layer, does add network, memory and CPU load to the transactions. If network bandwidth is your top issue, make sure your web service accepts and offers deflate/gzip compressed connections. This will reduce the cost of the Base64 data on the network layer, albeit at the cost of even more memory and CPU load.

These are architectural issues that should be discussed with your team and/or client.

Finally, let me give you a heads up about RoR's XML REST support. The Rails :binary database type will become <object type="binary" encoding="base64">...</object> XML objects when you render to XML using code like this from the default scaffolding:

def show
  @myobject = MyObject.find(:id)
  respond_to do |format|
    format.xml { render => @myobject }
  end
end

This works great for GET operations, and the PUT and POST operations are about as easy to write. The catch is the Rails PUT and POST operations don't accept the same tags. This is because the from_xml code does not interpret the type="binary" tag, but instead looks for type="binaryBase64". There is a bug with a patch at the Rails lighthouse site to correct this.

John Franklin
John! Thanks for the heads up.. especially the xml deserialization bug.
Jörg B.