You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@myfaces.apache.org by Aaron Bartell <aa...@gmail.com> on 2005/04/22 23:09:18 UTC

Download file from browser problem - two clicks

Below is the problem I am still having that I am wondering if anyone has
found a solution to.  Is there a way to make it so the user doesn't have to
click on the same link twice after a file download has occurred?  Almost
seems like something in the JSF lifecycle isn't completing correctly.  I am
returning null from action method of the link clicked so I stay on the same
page.  Any thoughts?

 

Thanks,

Aaron Bartell

 

 

 

 

 

Here is how I have done it based on things I have found on the net. The nice
thing about streaming it to the browser is that the file need not exist in
your context, it can be anywhere on the file system. The only bummer is that
this seems to create a problem after the user downloads. Any button or link
that they click after I do the .responseComplete() it doesn't work the first
time. But the second time they click the button or link it executes the
appropriate code. I am open to suggestions on any errors in my code to fix
that problem...

 


private void writeFileToBrowser(String fileSource, String downloadName,
String contentType) {

if (!FacesContext.getCurrentInstance().getResponseComplete() &&
FileControl.exists(fileSource)) {

HttpServletResponse response = (HttpServletResponse)
FacesContext.getCurrentInstance()
.getExternalContext().getResponse();
response.setContentType(contentType);
response.setHeader("Content-Disposition", "attachment;filename=\"" +
downloadName + "\"");

try {
ServletOutputStream out = response.getOutputStream();
BufferedInputStream bufferedinputstream = new BufferedInputStream(new
FileInputStream(
fileSource));

byte abyte0[] = new byte[4096];
int i;
while ((i = bufferedinputstream.read(abyte0, 0, 4096)) != -1)
out.write(abyte0, 0, i);

               out.flush();
               out.close();

 

               FacesContext.getCurrentInstance().responseComplete();
           } catch (IOException ex) {
               ex.printStackTrace();
           }
       }
   }

 

   public static boolean exists(String fileSource) {
       File f = new File(fileSource);
       return f.exists();
   }

 

HTH,
Aaron Bartell

 




Patrick B Haggood wrote:

 

Anyone have an example of downloading using MyFaces?  I see on the
sample you can use outputtext components, but that's using the real
filename (which I keep in a datastore to guard against duplicate
filenames; the system assigns new filename, FILE0002, FILE0003, etc
apon upload)

 

Thanks!

 


RE: Download file from browser problem - two clicks

Posted by Aaron Bartell <al...@gmail.com>.
That is the way I originally had it a couple months ago, but I have a large
repository of documents and to do what you are suggesting I would need to
store them in my context which would make war deployment incredibly painful.
Because of this I now store the files outside of the apps context and just
stream it out to the user.

 

I am guessing it has something to do with me using the responseComplete()
method but as of right now I have a beginners knowledge of the guts of the
JSF lifecycle and am not sure where to check and see the session state
malfunctioning. Note that I get zero error messages in my console and I have
it set to debug mode.

 

Check this out. I just changed my code to do nothing but get the request map
object, check to see if the response is complete, and if not, complete it.
The below produces a blank screen (but remains on the same URL).  So my next
question would be. am I doing anything "incorrect" here by prematurely
terminating the response?  I am assuming this would skip the render response
phase and that is why I get a blank screen.  If that is the case then I am
guessing the same thing is happening when I try to write a file out to the
browser, the render response phase is not getting executed and thus creating
the two clicks scenario because it needs to reinitialize something. ??? Am I
way off base?

 

    public void downloadPDF(ActionEvent event) {

        Document doc = (Document) UIHelper.getReqMapObj("document");

        if (!FacesContext.getCurrentInstance().getResponseComplete())

            FacesContext.getCurrentInstance().responseComplete();

    }

 

Thanks to everyone that has responded,

Aaron Bartell

 

  _____  

From: Heath Borders [mailto:heath.borders@gmail.com] 
Sent: Monday, April 25, 2005 8:02 AM
To: MyFaces Discussion
Subject: Re: Download file from browser problem - two clicks

 

The reason the user has to click twice is because the application state is
not getting saved properly for some reason.  My advice would be to just give
the user an <h:outputLink /> to your file rather than writing it out
yourself. 

On 4/22/05, Aaron Bartell <aa...@gmail.com> wrote: 

Below is the problem I am still having that I am wondering if anyone has
found a solution to.  Is there a way to make it so the user doesn't have to
click on the same link twice after a file download has occurred?  Almost
seems like something in the JSF lifecycle isn't completing correctly.  I am
returning null from action method of the link clicked so I stay on the same
page.  Any thoughts? 

 

Thanks,

Aaron Bartell

 

 

 

 

 

Here is how I have done it based on things I have found on the net. The nice
thing about streaming it to the browser is that the file need not exist in
your context, it can be anywhere on the file system. The only bummer is that
this seems to create a problem after the user downloads. Any button or link
that they click after I do the .responseComplete() it doesn't work the first
time. But the second time they click the button or link it executes the
appropriate code. I am open to suggestions on any errors in my code to fix
that problem... 

 


private void writeFileToBrowser(String fileSource, String downloadName,
String contentType) { 

if (!FacesContext.getCurrentInstance().getResponseComplete() &&
FileControl.exists(fileSource)) {

HttpServletResponse response = (HttpServletResponse)
FacesContext.getCurrentInstance() 
.getExternalContext().getResponse();
response.setContentType(contentType);
response.setHeader("Content-Disposition", "attachment;filename=\"" +
downloadName + "\""); 

try {
ServletOutputStream out = response.getOutputStream();
BufferedInputStream bufferedinputstream = new BufferedInputStream(new
FileInputStream(
fileSource));

byte abyte0[] = new byte[4096]; 
int i;
while ((i = bufferedinputstream.read(abyte0, 0, 4096)) != -1)
out.write(abyte0, 0, i); 

               out.flush();
               
out.close();

 

               FacesContext.getCurrentInstance().responseComplete();
           } catch (IOException ex) {
               
ex.printStackTrace();
           }
       }
   }

 

   public static boolean exists(String fileSource) {
       File f = new File(fileSource);
       return f.exists
();
   }

 

HTH,
 
Aaron Bartell

 








Patrick B Haggood wrote:

 

Anyone have an example of downloading using MyFaces?  I see on the
sample you can use outputtext components, but that's using the real
 
filename (which I keep in a datastore to guard against duplicate
filenames; the system assigns new filename, FILE0002, FILE0003, etc
apon upload)

 

Thanks!

 




-- 
-Heath Borders-Wing
hborders@mail.win.org  <ma...@mail.win.org> 


Re: Download file from browser problem - two clicks

Posted by Heath Borders <he...@gmail.com>.
The reason the user has to click twice is because the application state is 
not getting saved properly for some reason. My advice would be to just give 
the user an <h:outputLink /> to your file rather than writing it out 
yourself.

On 4/22/05, Aaron Bartell <aa...@gmail.com> wrote: 
> 
>  Below is the problem I am still having that I am wondering if anyone has 
> found a solution to. Is there a way to make it so the user doesn't have to 
> click on the same link twice after a file download has occurred? Almost 
> seems like something in the JSF lifecycle isn't completing correctly. I am 
> returning null from action method of the link clicked so I stay on the same 
> page. Any thoughts?
> 
>  Thanks,
> 
> Aaron Bartell
> 
>      Here is how I have done it based on things I have found on the net. 
> The nice thing about streaming it to the browser is that the file need not 
> exist in your context, it can be anywhere on the file system. The only 
> bummer is that this seems to create a problem after the user downloads. Any 
> button or link that they click after I do the .responseComplete() it doesn't 
> work the first time. But the second time they click the button or link it 
> executes the appropriate code. I am open to suggestions on any errors in my 
> code to fix that problem...
> 
>  
> 
> 
> private void writeFileToBrowser(String fileSource, String downloadName, 
> String contentType) {
> 
> if (!FacesContext.getCurrentInstance().getResponseComplete() && 
> FileControl.exists(fileSource)) {
> 
> HttpServletResponse response = (HttpServletResponse) 
> FacesContext.getCurrentInstance()
> .getExternalContext().getResponse();
> response.setContentType(contentType);
> response.setHeader("Content-Disposition", "attachment;filename=\"" + 
> downloadName + "\"");
> 
> try {
> ServletOutputStream out = response.getOutputStream();
> BufferedInputStream bufferedinputstream = new BufferedInputStream(new 
> FileInputStream(
> fileSource));
> 
> byte abyte0[] = new byte[4096];
> int i;
> while ((i = bufferedinputstream.read(abyte0, 0, 4096)) != -1)
> out.write(abyte0, 0, i);
> 
>                out.flush();
> 
>                out.close();
> 
>                 FacesContext.getCurrentInstance().responseComplete();
> 
>            } catch (IOException ex) {
> 
>                ex.printStackTrace();
> 
>            }
> 
>        }
> 
>    }
> 
>     public static boolean exists(String fileSource) {
> 
>        File f = new File(fileSource);
> 
>        return f.exists();
> 
>    }
> 
>  HTH,
> 
> Aaron Bartell
> 
>  
> 
> Patrick B Haggood wrote:
> 
>  Anyone have an example of downloading using MyFaces?  I see on the
> 
> sample you can use outputtext components, but that's using the real
> 
> filename (which I keep in a datastore to guard against duplicate
> 
> filenames; the system assigns new filename, FILE0002, FILE0003, etc
> 
> apon upload)
> 
>  Thanks!
> 
>  


-- 
-Heath Borders-Wing
hborders@mail.win.org