简体   繁体   中英

Vaadin FileDownload requires the button be clicked twice to download

I'm following the Vaadin sample code but when I do I require a second click to start the file download. Below is my code:

final StreamResource streamResource = new StreamResource(
        () -> {
            return new ByteArrayInputStream("hello world".getBytes());
        }, document.getName() + ".txt");

FileDownloader fileDownloader = new FileDownloader(streamResource);
fileDownloader.extend(getDownloadButton());

There's nothing special about the code to create the button but as requested in the comments here it is:

Button downloadButton = new Button("Download");

Although I don't like this solution it works. It has to do with how the download works and some restrictions by the browser. I'm sure there's a better solution but right now I simulate the first click with Javascript. If someone can find the correct answer then please post it and I'll change the selected answer, otherwise this is the only solution I found (posted in the Vaadin forums).

streamResource = createStreamResource();
downloadButton createDownloadButton();
downloadButton.setId("DownloadButtonID");

if(fileDownloader == null)
{
    fileDownloader = new FileDownloader(streamResource);
    fileDownloader.extend(downloadButton);
    // Javascript click so that it works without a second click
    Page.getCurrent().getJavaScript().execute(
           "document.getElementById('DownloadButtonID').click();");
} else {
    fileDownloader.setFileDownloadResource(streamResource);
}

The solution to the second click requirement for downloading the file is the button's listener . Like in my case, i have the click listener of button in which FileDownloader extends button. But it should be without listener only as FileDownloader has its own mechanism to handle the listener actions.

Here, the first button click gets handled by the clickListener and only in that, fileDownloader extends download button which holds all the functionality of downloading the file and this functionality occurs only when click event goes through the FileDownloader. so for the next time click goes through the FileDownloader as now its extending the button.

public static Button getDownloadButton(String fileName, String fileAsString, String caption) {
    // caption
    Button dwnButton = new Button(caption, VaadinIcons.DOWNLOAD);
    dwnButton.addClickListener(listener -> {
        StreamResource resource = createResource(fileName, fileAsString);
        FileDownloader fileDownloader = new FileDownloader(resource);
        fileDownloader.extend(dwnButton);
    });
    return dwnButton;
} 

Here, fileDownloader already extending the button and it has all the stream resources. So on the first click only downloading gets invoked.

public static Button getDownloadButton(String fileName, String fileAsString, String caption) {
    // caption
    Button dwnButton = new Button(caption, VaadinIcons.DOWNLOAD);
    StreamResource resource = createResource(fileName, fileAsString);
    FileDownloader fileDownloader = new FileDownloader(resource);
    fileDownloader.extend(dwnButton);
    return dwnButton;

}

To me, I inited FileDownloader in constructor with dummy resource:

if (fileDownloader == null) {
    fileDownloader = new FileDownloader(streamResourceDummy);
    fileDownloader.extend(button);
}

And set actual resource in button event listener:

buttonClick(ClickEvent event){
if (fileDownloader != null) {
// close previous stream
((StreamResource) fileDownloader.getFileDownloadResource()).getStreamSource().getStream().close();
    fileDownloader.setFileDownloadResource(streamResource);
}

}

And It works :)). I am using Vaadin 8.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM