Vaadin 10 autmoatically download a file without clicking a button

Hi All - I am generating a file in my application and I want to download it without the user having to click on a button.
I have the following code which creates the file to download and adds the Anchor button - but you still have to click the anchor button to actually download the file. Is there anyway of starting the download automatically?

private List<String> bodyList = new LinkedList<String>();
String timeStamp = (new Timestamp(new Date().getTime())).toString();

try {
	ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
	DataOutputStream out = new DataOutputStream(byteArrayOutputStream);
	for (String element : bodyList) {
	    out.writeBytes(element + "\n");
	}
		
	InputStream is = new  ByteArrayInputStream(byteArrayOutputStream.toByteArray());
		
	StreamResource myResource = new StreamResource(csvFileName, () -> is);
	Anchor downloadLink = new Anchor(myResource, "Download!");
	downloadLink.setId(timeStamp);
       downloadLink.getElement().setAttribute("download", true);
       hl.add(downloadLink);
} catch (IOException e) {
	e.printStackTrace();
}

Hello Brian,

you could trigger programmatically calling JavaScript:

public static void click(UI ui, Component... components) {
	Page page = ui.getPage();
	for (Component component : components) {
		page.executeJavaScript("$0.click()", component.getElement());
	}
}

after that:

click(ui,downloadLink);

Hi Diego,
Thank you for your help - it is now working

Regards
Brian

Browsers will generally block file downloads that happen without direct user interaction. It’s a security mechanism.

-Olli

Hello,
sorry I have the same problem.
I call a function that generates a file xls. After automatically i would download this file without button visible on the UI. How can i do this ?
Thank you

Hi,

can you briefly describe the process of how this would work, from the end user point of view? Just something like

1. User navigates into view
2. ???
3. Generated file starts downloading
``

-Olli

End user starts the process clicking a button. A file xls is generated and my goal is to open this generated file in excel or to download it locally. I would avoid a second click on another button to download or open.
Thank you

You should look at the Dynamic Content chapter in the docs: https://vaadin.com/docs/v11/flow/advanced/tutorial-dynamic-content.html

Take a look at this forum discussion as well: https://vaadin.com/forum/thread/17010389

-Olli

I read tutorial it but it doesn’t start download… Sorry but with Vaadin 7 was more simple !
My code is:

....
InputStream is=new ByteArrayInputStream(ous.toByteArray());
StreamResource myResource = new StreamResource("filename.xls", () -> is);
Anchor downloadLink = new Anchor(myResource, "");
downloadLink.getElement().setAttribute("download", true);
downloadLink.add(new Button(new Icon(VaadinIcon.DOWNLOAD_ALT)));
add(downloadLink)

but this add a button …
How can i do to start automatically download?

Hi,
You need to execute javscript:clickButton on you Anchor component - remember to set an id on the anchor component. You can also set the anchor component to invisible so it does not show on the page. This is the code that works for me:

private void downloadReport(List<String> bodyList, String csvFileName, HorizontalLayout hl) {
	
	try {
		ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
		DataOutputStream out = new DataOutputStream(byteArrayOutputStream);
		for (String element : bodyList) {
		    out.writeBytes(element + "\n");
		}
		
		InputStream is = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
		StreamResource myResource = new StreamResource(csvFileName, () -> is);
		Anchor downloadLink = new Anchor(myResource, "Download");
		downloadLink.setId(timeStamp);
		downloadLink.getElement().getStyle().set("display", "none");
		downloadLink.getElement().setAttribute("download", true);
		hl.add(downloadLink);
        
		Page page = UI.getCurrent().getPage();
		page.executeJavaScript("document.getElementById('"+timeStamp+"').click();");
	} catch (IOException e) {
		e.printStackTrace();
	}
}

ok… I will try
Thank you !