How to download a file with a dialog in Vaadin?

Here is the scenario:

I have an http url representing image/video/plain text or any file type. Just assume that it is a simple direct url. When I click the download button, the file should be downloaded from the url to the system with a dialog as in below snapshot.

File name and file type would be dynamic.

I do not want to open a new browser tab for this purpose as the best user experience is just to prompt the download straight away. How do I do this in Vaadin? My Vaadin version is 23.2.0

I’m thinking how would I write the button click listener to achieve this?
unknown.png

Bumping up this post.

You can use the Anchor element with a download attribute. Here’s a tutorial Enable Users to Upload & Download Files | Vaadin

@secure-leopard
Thanks for the info.

In fact, I could think of this way:

Anchor download = new Anchor(new StreamResource("filename.ext", () -> createResource()), "");
  download.getElement().setAttribute("download", true);
  download.add(new Button(new Icon(VaadinIcon.DOWNLOAD_ALT)));

But the link href is still static. I have a text label and user input some text there. When the user click on download button, it is going to dynamically find the download url (based on the value entered in textfield) from which the file is downloaded. I’m afraid I can only go for button addClickListener in this case. At this point vaadin button has the click listener part, but only vaadin anchor has the direct download feature. Let me know if you understood the problem.

Based on a user-input (text label), I want to download from a dynamic url (button click event).


downloadButton.addClickListener(e -> {
   String downloadUrl = findUrl(textField.getValue());
   StreamResource resource = new StreamResource("file.jpg", () ->     {
          return new URL(downloadUrl).openStream();
   });
   
   //I have the download url ready, resource created 
   //But how can I get it downloaded in the next step?
   // Seems like I can't achieve click listener in anchor
});


Just use viritin if you don’t wanna go the extra mile https://github.com/viritin/viritin/blob/master/viritin/src/main/java/org/vaadin/viritin/button/DownloadButton.java

@quintessential-ibex I still don’t know why this isn’t in the core :wink:

How can I achieve the above mentioned behavior if I use DownloadButton
I have been following this:
https://github.com/viritin/viritin/blob/d59548d2ef42e57d178ac9569dbf949434f40f86/viritin/src/test/java/org/vaadin/viritin/it/DownloadButtonExample.java#L62

It too have a click listener, but ends up in the same situation as in normal button (where I create the resource dynamically, but don’t know how to download). How can I download from a dynamic url and prompt for download?

Above that code is everything you need, a callback once the button is clicked as well as mine type and file name provider to customize it depending on the value of your text field

Once the button is clicked the user should get a download prompt / or it’s automatically downloaded and can be seen in the Browser tray

can I style the DownloadButton like this?

downloadButton.addStyleName(ButtonVariant.LUMO_PRIMARY.getVariantName());

And how to set label for DownloadButton ?

Also, the below line gives me error when using with DownloadButton

buttonLayout.add(downloadButton); // buttonLayout is a horizontal vaadin layout

The method add(Component…) in the type HasComponents is not applicable for the arguments (DownloadButton)

It should all work, in the end it’s just extending Button. So like you style and use any Vaadin Button

why I was saying because:
button.addThemeVariants and buttonLayout.add(button) are throwing error while using with DownloadButton

I see it is an extension of button, but it is throwing errors on these existing methods and I was wondering how to achieve the same results (setting the label, theme variants, adding it to a layout etc)

How do I add DownloadButton to a layout ? it isnt working, so

As a sidenote, the below line gives me error

buttonLayout.add(downloadButton); // buttonLayout is a horizontal vaadin layout
``
It is complaining that `DownloadButton` is not a component! It can't seem to work.

You have to do something wrong. Please check your imports, you can even see that it’s extending Vaadin’s Button class and because of that you can call any methods you normally do on a button.

``
import com.vaadin.flow.component.html.Div;

@Route(value = “some-view”, layout = MainLayout.class)
public class SomeView extends Div {
DownLoadButton downLoadButton = new DownloadButton(out → {
out.write(“some data”);
} );
// add(downLoadButton) //this fails as well
HorizontalLayout buttonLayout = new HorizontalLayout ();
buttonLayout.add(downLoadButton) // this is failing
add(buttonLayout);
}
``

This is the main class that looks fine for me.
And I just import this: import org.vaadin.viritin.button.DownloadButton;

Hard to tell what’s wrong here. It looks fine, probably an idea caching problem because of the new library

@sanguine-whale, what would you say about adding DownloadButton to Flow core?