Blog Archive

Friday, February 20, 2015

Tutorial: How to transfer binary files (pdf,images etc) in json


This is a common scenario in most of today web apps.
Today's web applications heavily rely on json for client server communication. Because json is a totally text based standard it goes very well until we need to send anything which is not text, like pdf files and images. And it is not a good idea that you implement a separate module to transfer binary files, it will defeat the whole purpose of using json.
I my self struggled a lot to find a good solution for this. And I didn't found a strait forward and simple tutorial to handle binary files with json.
So I decided to write one. Please share your comments and suggestions so I can Improve it.

Theory:
As json only supports text so we have to convert binary file (pdf, image etc) in to a string. And then we can easily add it to a json field.

Code Example: In my example I am using java for server end but you can use your own tools and languages, Theory will remain same.

I am assuming that you are familiar with jsp-servlet development thats why I am leaving out unnecessary implementation details of J2EE application.

Required jar Files : commons-codec-1.5.jar

Server End:

//Servlet

public class GetPdfServlet extends HttpServlet
{
public void doPost(HttpServletRequest request,HttpServletResponse response )
{
doGet(request,response);
}
public void doGet(HttpServletRequest request,HttpServletResponse response )
{
PrintWriter pw = null;
try{
pw = response.getWriter();

ByteArrayOutputStream ba= loadPdf(“myFile.pdf”);

//Converting byte[] to base64 string
//NOTE: Always remember to encode your base 64 string in utf8 format other wise you may always get problems on browser.
String pdfBase64String = org.apache.commons.codec.binary.StringUtils.newStringUtf8(org.apache.commons.codec.binary.Base64.encodeBase64(ba.toByteArray()));
//wrting json response to browser
pw.println("{");
pw.println("\"successful\": true,");
pw.println("\"pdf\": \""+pdfBase64String+"\"");
pw.println("}");
return;
}catch(Exception ex)
{
pw.println("{");
pw.println("\"successful\": false,");
pw.println("\"message\": \""+ex.getMessage()+"\",");
pw.println("}");
return;
}
}

private ByteArrayOutputStream loadPdf(String fileName)
{
File file = new File(fileName);
FileInputStream fis = new FileInputStream(file);
ByteArrayOutputStream bos = new ByteArrayOutputStream();

byte[] buf = new byte[1024];
try {
for (int readNum; (readNum = fis.read(buf)) != -1;) {
bos.write(buf, 0, readNum); //no doubt here is 0
}
} catch (IOException ex) {
ex.printStackTrace();
}
return bos;
}
}


Client End :

index.html

<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>Example</title>
<script type="text/javascript" src="/js/loadPdf.js"></script>
</head>
<body>
<div id='dataFormContainer'>
</div>
<form>
<input type='button' value='getPDF' onClick='getPdf()'>
</form>
</body>
</html>

LoadPdf.js

function getPdf()
{
var ax = getXMLHttpRequest();
ax.open('POST', "[your servlet url]",true);
ax.onreadystatechange=function()
{
if(ax.readyState==4 && ax.status==200)
{
var dataFormContainer = document.getElementById("dataFormContainer");
var response = eval("("+ax.responseText+")");
if(response.successful)
{
var url = "data:application/pdf;base64,"+response.pdf;
var _iFrame = document.createElement('iframe');
_iFrame.setAttribute('src', url);
dataFormContainer.appendChild(_iFrame);
}
}
}
ax.send();
}

NOTE: Always remember to encode your base 64 string in utf8 format at server end other wise you may always get problems on browser.