Solved

Download File problems using Struts, JSP or Servlets

Posted on 2003-11-13
17
12,064 Views
Last Modified: 2007-12-19
I have a JSP application that allows a user to select multiple files,
compress them and download the resulting zip file.  However once the file
has been download the links in the JSP page no longer work.

I have searched forums and tried many ways to do this (Struts action, JSP page, Servlet),
but as yet I have not found a solution to this particular problem.

I realise that it is because i am writing the contents of the file to the response and then
asking the response to redirect to another page.  That said, it is only Internet Explorer that
kicks up a fuss over this (executing my code) and I have seen other 'third party' packages
that provide a solution, so it must be possible!

I don't mind if the solution is a servlet or JSP as long as it is clean.
At the moment I get round it by calling the download code (in this case Struts action)
with target="_new".  this pops up a new window and starts the download.

I would prefer to do it a cleaner way.

Here is the code:

package com.ral.isis.icat.editor.download.action;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionError;
import org.apache.struts.action.ActionErrors;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletOutputStream;

import java.net.*;
import java.io.*;

import com.ral.isis.icat.editor.edit.form.DatafileForm;

public class DirectDownloadAction extends Action  {
  /**
   * This is the main action called from the Struts framework.
   * @param mapping The ActionMapping used to select this instance.
   * @param form The optional ActionForm bean for this request.
   * @param request The HTTP Request we are processing.
   * @param response The HTTP Response we are processing.
   */
  public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {

    DatafileForm myForm = null;
    String filename = null;
    String filepath = null;

    if (form instanceof DatafileForm) {
        myForm = (DatafileForm)form;
        filename = myForm.getName().trim();
        filepath = myForm.getPath().trim();

        if (filename != "" && filename != null) {
            String outfilename = filename;            
            File f = new File(filepath + filename);

            if (f.exists()) {
                response.setContentType("multipart/zip");
                response.setHeader("Content-Disposition","attachment; filename=\"" + filename.trim().substring(1,filename.length()) + "\";");    
                response.setContentLength((int)f.length());
 
                try {
                    OutputStream os = response.getOutputStream();
                    FileInputStream stream = new FileInputStream(f);
                    BufferedInputStream  bis = new BufferedInputStream(stream);
                    InputStream is = new BufferedInputStream(bis);
                    int count;
                    byte buf[] = new byte[4096];
                    while ((count = is.read(buf)) > -1)
                    os.write(buf, 0, count);
                    is.close();
                    os.close();
                } catch (Exception ex) {
                  ex.printStackTrace();
                }//end try/catch

            } else {
                   System.out.println("file doesn't exist: " + filename);
            }//end if
    }//end if    

    }//end if

    return mapping.findForward("success");
  }//end method
}//end class


Can anybody help me??!!!

Thanks,

Damian
0
Comment
Question by:u9707118
  • 7
  • 4
  • 4
  • +1
17 Comments
 
LVL 14

Expert Comment

by:kennethxu
ID: 9742545
Welcome your first question in experts-exchange ;)

the problem is in this 2 lines of code:
                response.setContentType("multipart/zip");
                response.setHeader("Content-Disposition","attachment; filename=\"" + filename.trim().substring(1,filename.length()) + "\";");

have a look at my answer in this Q:
http://www.experts-exchange.com/Web/Web_Languages/JSP/Q_20565283.html

let me know if you have further inquires.
0
 
LVL 14

Expert Comment

by:kennethxu
ID: 9742591
forget to mention that there was a problem in my code. you should always use application/unknow for force save as:

                        String contentType = "application/unknow";
                        response.setHeader( "content-type", contentType );
                        response.setHeader("Content-Disposition","attachment; filename=\"" + filename + "\"");
0
 

Author Comment

by:u9707118
ID: 9747850
Hi Kennethxu,

thanks for the welcome!
I have tried your solution, but I am still faced with the original problem...

once i have downloaded the file (or clicked the download button), the navigation links no longer work.

Something which I didn't notice before is that it is only links outside the frame which do not work.
i.e. I have a banner(top), navigation(side) and main page using frames.  Once I have downloaded a file, links from the 'side' and 'top'
frames no longer have any effect!

I have just inserted a link to 'google.com' in the main download page.  Once i have downloaded the file, I click this link and google loads up fine
within the main page.  However, I need the links in the 'side' and 'top' frames to work!

Sorry for the trouble, I have just noticed that it is the frames causing this problem!
But to re-iterate there is no problem in netscape/mozilla but now I am not sure that
the third-party solutions will work because the demonstrations are not included within any frames!

I still hope there is a workaround!

Damian
0
 
LVL 14

Expert Comment

by:kennethxu
ID: 9748278
I believe this is IE's problem, did you tried from another PC?
0
 

Author Comment

by:u9707118
ID: 9748363
Yes, problem is with IE and have tried on another PC.
Dammit, I need to use frames aswell!

Damian
0
 
LVL 14

Expert Comment

by:kennethxu
ID: 9749877
>> once i have downloaded the file (or clicked the download button), the navigation links no longer work.
try to use a link instead of a button for download url.
0
 

Author Comment

by:u9707118
ID: 9762353
Sorry for not getting back sooner,
was away at the weekend.

I have just tried swithing to a link instead of a button for download URL.
I have also tried switching from links to buttons for the navigation url's as well!

Unfortunately neither effort has made a difference.

Damian
0
 
LVL 6

Expert Comment

by:jarasa
ID: 9777531
Hello Damian.

I know Your Problem, ha ha, and is true tahs is an iExplorer proble wich they don't deem to resolve, What I did to solve mine was to pop up a new window wich sends the Download.

The problem is that after the download the JavaScript stops working on the souce page and that's why it still works in other frames. We solved the problem first by sending the download throught a hidden frame on the same window but we decided that was better to pop up a new window, but both ways work, the only problem with the popup window is that there is no way to control if the user has closed it or not and if he makes more than one download and you are using the same window name so it opens only one it could loose the previous download.

Anyway I think you should try the hidden frame option is much clear I'm not really sure if I stiil have that code some where but if I' find it I'll put it here so you can see it, ok?

the popup one is this way:

function download() {
var params = genParams(); // you have to take the form to resend it in post mode
params += "Extra information if you have ";
var url = "your servlet or jsp" + params;
window.open(url,400,200,null,null,'');
}

Have Fun
Javier
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 

Author Comment

by:u9707118
ID: 9777590
Hi jarasa,

I would be very interested in trying the hidden frame option if you can find the code!

thanks,
Damian
0
 
LVL 6

Accepted Solution

by:
jarasa earned 250 total points
ID: 9777860
Hi Damian.

I've been looking for it but I can't find it, but anyway it wasn't too hard, the thing to do is to create a frameset if you don't have already one with a frame with size = 0 this way:

<frameset rows="*,0" cols="100%" frameborder=0 framespacing=0>
      <FRAME NAME="Body" scrolling="no" frameborder=0 framespacing=0 marginwidth=0 marginheight=0 noresize="true" src="your JSP">
      <frame name="Download" scrolling="no" frameborder=0 framespacing=0 marginwidth=0 marginheight=0 noresize="true" src="empty.html">
      <noframes>
            No frames Supported.
      </noframes>
</frameset>

Then on the submit of your Jsp you redirect to the empty frame with target="Download" the only problem that we found and one of the reasons we dicided to use the pop window was becose of Netscape, with Netscape you don't have this problem and woks ok with the hidden frame but the problem is that you can't make a Frame of size=0 it has to be at least 1 pixel size, and that was a problem for us becose our application window size is fixed to 800x600 and you could see the pixel line, wich was undesired.

Tell me if you can do it, ok?

Have Fun.
Javier
0
 

Author Comment

by:u9707118
ID: 9777892
Ok, Javier

Thanks for posting the code,
I will give it a try this afternoon and then I will get back to you!

Thanks
D.
0
 
LVL 6

Expert Comment

by:jarasa
ID: 9777912
Damian.
One important thing is what kennethxu said:

>>forget to mention that there was a problem in my code. you should always use application/unknow for force save as:

                        String contentType = "application/unknow";
You don't want the iexporer to open the downloaded file into your hidden frame, :c))

Javier


0
 

Author Comment

by:u9707118
ID: 9779730
Hi Javier,

Thanks for your help!
I have just inserted another (hidden) frame into the frameset
and directed my form submission to this frame via the 'target' attribute.

i.e.  <html:form action="/directDownload" target="downloadFrame">

The form is submitted to my servlet, the file download starts and all the links still work!
Works fine in Netscape/Mozilla as well!

Problem solved,
I will now award my first points in EE!
Again, thanks for your help.  This has made my day because this problem has been bugging me for weeks.

Cheers,
Damian
0
 

Expert Comment

by:aguynextdoor
ID: 10427511
Hello u9707118

I have a similar requirement  and I am new to struts.
Would you mind posting the frame code.
I have action class which sets the reponse for the zip file download but i didn't quite understood
the frame redirection expalined in the topic

-harsh
0
 
LVL 6

Expert Comment

by:jarasa
ID: 10430429
Harsh.

You just have to make the FRAMSET and put in the <FORM ....... target="FrameName"> that's all.

Javier
0
 

Author Comment

by:u9707118
ID: 10430509
The code below describes a common frameset (i.e. top/header frame, (left)side/nav frame and main contents.
If you look carefully, I have one more frame ('downloadFrame') to the extreme right and its size is set to 0 (making it invisible).

Now when you have a link to your action that produces/spits back the zip file make sure the link has target='yourHiddenFrameName'.  That's it. Now the only page that breaks is one that the user
cannot see or use...so it doesn't matter!

Hope this helps,

Damian


<HTML>
<HEAD>
<LINK REL=STYLESHEET TYPE="text/css" HREF="bc4j.css">
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<TITLE>ISIS Catalogue</TITLE>
</HEAD>
<FRAMESET rows="145,*" FRAMESPACING="0" FRAMEBORDER="0" border="false" >
   <FRAME SRC="Title.jsp" NAME="titleFrame" FRAMEBORDER="0" MARGINHEIGHT="10"
          MARGINWIDTH="10" FRAMESPACING="0" SCROLLING="NO">
   <FRAMESET cols="370,*,0" FRAMESPACING="0" FRAMEBORDER="0" SCROLLING="AUTO">
      <FRAME SRC="Contents.html" name="navFrame">      
      <FRAME SRC="Description.html" name="contentsFrame">
            <FRAME SRC="HiddenDownloadPage.jsp" name="downloadFrame">
   </FRAMESET>
</FRAMESET>
</HTML>
0
 

Expert Comment

by:aguynextdoor
ID: 10448562
Thanks for the code.

I think I am stuck on the zip file creation.
here is my code , please let me know what i am doing wrong
I am getting empty  zip file.
In the while loop i get  all the content for all individual files but for some reason zip file is not getting created properly.

Please help, I am really stuck on it.
 
here is my fileObj look like

public class XMLfileObj  //
{  
    private String fileName;    
    private ByteArrayOutputStream contentOutputStream;
}



In the struts action class - execute method



//this will force to open the dialog box for download
response.setContentType( "application/octet-stream" );
response.setHeader( "Content-Disposition",    "attachment; filename=\"" + suggestedName + "\"" );
String suggestedName = "myresutl.zip";

//zip file
ZipOutputStream   outfile = new ZipOutputStream( new FileOutputStream( suggestedName) );

// iterator of XMLfileObj  
Iterator noOfFiles = (Iterator) map.get( IAppConstants.BATCH );

   
while ( noOfFiles.hasNext(  ) )
 {

XMLfileObj fileObj=null;
String fileName =null;

fileObj= (XMLfileObj) noOfFiles.next(  );
fileName= fileObj.getFileName(  );
ZipEntry e = new ZipEntry( fileName );
outfile.putNextEntry( e );
ByteArrayOutputStream baos = fileObj.getContentOutputStream();
baos.writeTo(outfile);
outfile.closeEntry(  );
}
outfile.close();//close zip file              

OutputStream os = response.getOutputStream(  );

FileInputStream fis = new FileInputStream(suggestedName);
int len;
byte[] b = new byte[4096];
while ( (len = fis.read(b)) != -1 )
 {
 os.write(b, 0, len);
}
fis.close();
os.close(  );

return mapping.findForward( "download" );
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Are you unable to connect or configure Hotmail email account in Microsoft Outlook 2010, 2007? Or Outlook.com emails are not downloading to Outlook? Lets’ see the problem and resolve Outlook Connector error syncing folder hierarchy (0x8004102A).
A Short Story about the Best File Recovery Software – Acronis True Image 2017
Internet Business Fax to Email Made Easy - With eFax Corporate (http://www.enterprise.efax.com), you'll receive a dedicated online fax number, which is used the same way as a typical analog fax number. You'll receive secure faxes in your email, fr…
Get a first impression of how PRTG looks and learn how it works.   This video is a short introduction to PRTG, as an initial overview or as a quick start for new PRTG users.

743 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now