2

i have problem with <p:fileDownload> when i try to download file and bean throws exception page reloaded and removes parametr from url:

 <p:commandLink update=":gform:growl" ajax="false"
                                   onclick="PrimeFaces.monitorDownload(null, stop)">
                        <i class="fa fa-paperclip fa-2x sc-badge-icon sc-border-right hover"></i>
                        <p:fileDownload value="#{taskFileController.getFile(cc.attrs.scFile)}"/>
                    </p:commandLink>

bean code:

public void getFile(ScFile scFile) throws IOException {
    try {
        File file = ftpController.downLoadFile(scFile);
        HttpServletResponse response = (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();
        response.setHeader("Content-Disposition", "attachment;filename=\"" + scFile.getFileName() + "\"");
        response.setContentLength((int) file.length());

        input = new FileInputStream(file);
        byte[] buffer = new byte[1024];
        out = response.getOutputStream();
        while (input.read(buffer) != -1) {
            out.write(buffer);
            out.flush();
        }
        FacesContext.getCurrentInstance().getResponseComplete();
    } catch (GrowlException e) {
        GrowlException.show(e);
    } catch (Throwable err) {
        err.printStackTrace();
        GrowlException.show("Возникла ошибка при скачивании файла");
    }
}

P.s. when no exception page do not reloaded. P.s.s. bean is @Named and @Stateless

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555

2 Answers2

2

As stated on the Primefaces showcases your getFile() method must return a StreamedContent instead of writing to the response output and the return value may not be null:

public StreamedContent getFile(ScFile scFile) throws IOException {
    File file = ftpController.downLoadFile(scFile);
    InputStream stream = new FileInputStream(file);
    String filename = scFile.getFileName();
    String contentType = "attachment;filename=\"" + scFile.getFileName() + "\"";
    StreamedContent file = new DefaultStreamedContent(stream, contentType, filename);

    return file;
}

Preventing it from being null due to whatever cause can be solved in a good or dirty way:

  1. (dirty) Simply provide an empty DefaultStreamdContent:
    new ByteArrayInputStream(new byte[] {});
  2. Create a two stage download process. First you use an ajax button which the user presses in order to determine if the file is available. The user then receives a second link (the pf download button) in order to download the content you have already prepared in your bean.
Dennis Kriechel
  • 3,719
  • 14
  • 40
  • 62
  • does not matter, page reloaded when StreamedContent returns null (on exception) – George Vassilev Dec 11 '15 at 08:47
  • @GeorgeVassilev The page will allways reload if an error is thrown in your jsf, you need to prevent StreamContent from being null – Dennis Kriechel Dec 11 '15 at 08:48
  • how i can pass reload ? becouse this removing `taskid` from url – George Vassilev Dec 11 '15 at 08:50
  • if the reload was triggered by an exception, you can't, if the reload was triggered by the download button you check this link on how to add parameters to a button: http://stackoverflow.com/a/4994833/2546444 – Dennis Kriechel Dec 11 '15 at 08:59
  • 1
    As @DennisKriegel states, prevent the situation from happening. Make sure there is no and can't be an error. – Kukeltje Dec 11 '15 at 09:00
  • @Kukeltje im not understand, if method `getFile` return `null` jsf\primefaces considers this exception ? – George Vassilev Dec 11 '15 at 09:58
  • Yes, and validly so...it is a ***programming/design*** error. How can getFile() return null? If the file is not available? Then prevent the download button from being active ***that*** is how you solve things... ***upfront*** – Kukeltje Dec 11 '15 at 10:06
  • @Kukeltje return null when no permission to that file,not avalible etc.... And very strangely PF reload page on this error , while i`m handling on bean this and send message with error to UI; – George Vassilev Dec 11 '15 at 10:20
  • 1
    No, not strange, you use `p:fileDownload` in a wrong way as @DennisKriechel pointed out in the answer. **Your** implementation is for the non-p:fileDownload download (plain jsf) way... Search stackoverflow for full solutions... – Kukeltje Dec 11 '15 at 10:23
  • 1
    there are two way you can go, a dirty one and a fine one: 1. (dirty) Simply provide an empty DefaultStreamdContent (`new ByteArrayInputStream(new byte[] {});`) 2. Create a two stage download process. First you use an ajax button which the user presses in order to determine if the file is available. The user then receive a second link (the pf download button) in order to load the content you have already prepared in your bean. – Dennis Kriechel Dec 11 '15 at 10:28
0

I came across the same problem where I don't want to refresh the page if the file to download is null. I solved the problem by disabling the button that let the user download the file by generating the file before the actual download and checking his existance:

<p:commandButton disabled="#{ReportBean.contentToDownload eq null}">
    <p:fileDownload value="#{ReportBean.downloadPdf()}"/>
</p:commandButton>

I find this solution more elegant than letting user click twice. Users hates clicking twice.

Simone Lungarella
  • 301
  • 1
  • 4
  • 15