Monday, November 21, 2011

Download a file without Server trip - HTML + JSP

Hi,
Many times we as a developer has data on client side for the end user and on his request wants to prompt user (Save As dialog box) to download that data.
The solution to download local/client-side contents via javascript is not straight forward. I have implemented one solution using SmartClient, Html and JSP.

Being a developer and not a good philosopher 'm coming straight to the solution:

Problem:
I am in the project in which client side is implemented in SmartClient8. We need to download/export data of a grid (a table like structure). We were using RESTish web services to serve the data from Server side. So I want to ignore the server call for the same data to download that I am showing in the grid.

Solution:
What I did is made two JSPs namely: blank.jsp and export.jsp.
File blank.jsp is literally blank, absolutely no code. Now I need to export the grid data that I already have on client side in JSON format [JavaScript Object Notation - you can google it :)].
Now when ever user asks to export the grid data (by clicking a button on UI), I do below:
    a. Open a new window with url blank.jsp
    b. using document.write I create a form in it with one field name text in it and set data to export inside it.
    c. Now POST that form to export.jsp present in same hierarchy.
    d. I am pasting code of export.jsp and is self explanatory.

// -------------------------- code start -------------------------------------

<%@ page import="java.util.*,java.io.*,java.util.Enumeration"%>
<%
response.setContentType ("text/csv");
//set the header and also the Name by which user will be prompted to save
response.setHeader ("Content-Disposition", "attachment;filename=\"data.csv\"");
String contents = request.getParameter ("text");
if (!(contents!= null && contents!=""))
contents = "No data";
else
contents = contents.replaceAll ("NEW_LINE", "\n");

//Open an input stream to the file and post the file contents thru the
//servlet output stream to the client m/c

InputStream in = new ByteArrayInputStream(contents.getBytes ());
ServletOutputStream outs = response.getOutputStream();

int bit = 256;
int i = 0;
try {
while ((bit) >= 0) {
bit = in.read();
outs.write(bit);
}
//System.out.println("" +bit);
} catch (IOException ioe) {
ioe.printStackTrace(System.out);
}
outs.flush();
outs.close();
in.close();
%>



<%script type="text/javascript">
try {window.close ();} catch (e) {alert (e);}
<%/script>



// -------------------------- code end -------------------------------------

Above functionality is cross-browser and working fine on IE, FF, Safari, Chrome.
This code is tested, deployed and working in production environment.


Thanks shaILU