0

I habe a Vaadin 23 app running on a wildfly server. I want to add a button which then start to download a file which is located under the web-inf directory. I only found this blog article which seems to be outdated.

Which is the best (preferred) way to achieve this?

Thanks and kind regards Matt

Matt
  • 75
  • 14

2 Answers2

1

One approach is to get the file as resource and set it to Anchor. Then you can have a Button which programmatically clicks the Anchor.

Anchor anchor = new Anchor();
anchor.setText("Download");
anchor.getElement().getStyle().set("display", "none");
anchor.getElement().setAttribute("download", true);

anchor.setHref(resource);
Button button = new Button("Download");
button.addClickListener(event -> {
    anchor.getElement().callJsFunction("click");
});
add(anchor, button);

There is also an add-on in Vaadin's Directory that packages the above process.

Note, if you want to have the Download button in the Dialog, make sure that Anchor is not in the Dialog, see another question.

You can find also more complete download example here.

Tatu Lund
  • 9,949
  • 1
  • 12
  • 26
0

Thanks I came up with this method:

private Button createDownloadButton(String fileName) {
    Icon icon = VaadinIcon.FILE_TABLE.create();
    icon.setColor("green");
    Button downloadButton = new Button(fileName, icon);
    downloadButton.addThemeVariants(ButtonVariant.LUMO_TERTIARY);
    downloadButton.setDisableOnClick(true);
    downloadButton.addClickListener(event -> {
        InputStream inputStream = VaadinServlet.getCurrent().getServletContext()
                .getResourceAsStream(UiFactory.DOWNLOAD_PATH + fileName);
        ReadableByteChannel readChannel = Channels.newChannel(inputStream);
        Path downloadPath = Paths.get(System.getProperty("user.home"), fileName);
        FileChannel writeChannel = null;
        
        try(FileOutputStream fileOS = new FileOutputStream(downloadPath.toFile())) {
            writeChannel = fileOS.getChannel();
            writeChannel.transferFrom(readChannel, 0, Long.MAX_VALUE);
            String message = String.format("Successfully transferred file to %s.", downloadPath.toString());
            showStatusMessage(message, null, MessageStatus.SUCCESS);
            downloadButton.setEnabled(true);
        } catch (IOException exception) {
            // handle IO exceptions
        } finally {
            try {
                if (writeChannel != null){
                    writeChannel.close();
                }
                readChannel.close();
            } catch (IOException e) {
                // handle IO exceptions
            }
        }
    });

Problem here is that there is no dialog to ask the user where to store the file. So the JS solution is pretty smart here.

Matt
  • 75
  • 14