Search code examples
jsfnavigationdownload

Perform page navigation and send redirect after a file download


I need to find a way to perform a page navigation after generating a file download. So far, I've got the file download ready and working:

FileInputStream stream = new FileInputStream(file);
        FacesContext fc = FacesContext.getCurrentInstance();
        ExternalContext ec = fc.getExternalContext();
        ec.responseReset();
        ec.setResponseContentType("application/octet-stream");
        ec.setResponseHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");

        OutputStream out = ec.getResponseOutputStream();

        byte[] outputByte = new byte[4096];

        while(stream.read(outputByte, 0, 4096) != -1)
        {
                out.write(outputByte, 0, 4096);
        }
        stream.close();
        out.flush();
        out.close();
        fc.responseComplete();

So far, I've try redirecting from the ExternalContext afterwards but i get an IllegalStateException.

ec.redirect(url)

I've also tried wrapping all the previous code in a string method that returns the page to be navigated at the end. That didn't work either.

Any recommendations?


Solution

  • You can't return 2 responses to 1 request. You can return only 1 response to 1 request. A file download counts as one response and a redirect counts as another response.

    Your best bet is to return a response which automatically initiates a new request in some way. The second response can then be returned to this automatically initiated request. JavaScript is very helpful in this with functions like window.location (to fire a new request in current window), window.open() (to fire a new request in a new window), and form.submit() (to submit a POST form).

    The simplest way would be to redirect to the target page wherein some JavaScript is conditionally rendered (and immediately executed) which in turn triggers the file download by e.g. window.location or form.submit(). The window.open() is inappropriate if the download itself is already set as an attachment. Note that this approach doesn't redirect after the user has saved the file download, this is plain impossible as there's no client side event to hook on when the last bit of the download is saved. Instead, the redirect is first performed and then the file download.

    See also: