Sunday, February 24, 2008

Implementing File download feature in Struts 2 & Struts

Although file upload is a common feature that many struts application developers implement , it is less common to implement file download , in this post we will see how to provide file download feature in your struts 2 application.

Before we see how to implement this feature, let us first understand the requirement

1) A web page contains a link , which upon clicking it responds with a browser's file save dialog with a default name
2) User can choose the save location to save the file (as with any file save dialog)

This example uses a simple ActionClass with name DownloadAction and a jsp to show the link for downloading an arbitrary file



Let us start with the JSP , this is the simplest thing with a link pointing to the action class


Click to download


The action class which provides the download of file just needs to implement the getInputStream() method returning the InputStream of the required file to dowload !! Simple ...isn't ?

DownloadAction.java

public class DownloadAction {
private String fileName="YOUR FILE PATH";
public InputStream getInputStream(){
try{
return new FileInputStream(new File(fileName));
}catch(Exception e){}
}
public String execute(){
return "success"
}
}


Now the final thing is to wire these up in struts.xml , NOTE... there is something that is different from other regular configurations!! ... unlike other cases the control need not be passed to the JSP , instead we want the content to be handled by the browser itself (to bring up required download dialog), hence the result type is specified as "stream", which by default looks for getInputStream method (it can be configured) and sends it back as response














Easy !! isn't ? Then how about the implementation in Struts 1.xx ?

We can achieve this with the following steps

1) In the Action Class obtain the servlet response object
2) get the OutputStream from the response object
3) Get the InputStream of the target file (which we want to send to the browser)
4) Write the contents of the file to the Outputstream of step #2.
5) Don't forward the request by returning null to terminate the action.

Now, let us take a look at the code snippet of the DownloadAction.


...
...
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
File f = new File("C:\\myTestFile.xml");
response.setContentType("application/octet");
byte[] buffer = new byte[2048];
FileInputStream inputStream=new FileInputStream(f);
int bytesRead = inputStream.read(buffer);
ServletOutputStream outputStream=response.getOutputStream();
while (bytesRead >= 0) {
if (bytesRead > 0) {
outputStream.write(buffer, 0, bytesRead);
}
bytesRead = inputStream.read(buffer);
}
outputStream.flush();
//no need to forward ..
return null;
}


Here for the sake of brevity I have hardcoded the file name you will get the file name Or file Object probably from your models or from the form ..(Or any other way)

Thats it!! Hope it helps