Intermittent 404 Error with FileDownloadWrapper in Firefox

Hello everyone,

I am using the FileDownloadWrapper add-on from the Vaadin directory to programmatically trigger a file download. My implementation works perfectly in Chrome and other browsers, but I’m facing an intermittent “404 Not Found” error specifically in Firefox.

The goal is to have a method that, when called, creates a temporary download button, wraps it with FileDownloadWrapper, programmatically clicks it to start the download, and then removes it from the UI.

The Issue and Error Message

The process works inconsistently in Firefox. Sometimes the download starts correctly, but other times Firefox displays a “404 Not Found” error page.

Interestingly, when my Firefox browser language was set to Italian, the download failed consistently. After switching the browser language to English, it started working but still fails intermittently.

Here is the error page shown by Firefox:


Looks like there’s a problem with this site

http://localhost:8080/VAADIN/dynamic/resource/1/d4433986-9d56-4df1-8b22-7ee3603d7877/Pdf_scenario_Trauma_Cranico_in_Vigile_Urban.zip might have a temporary problem or it could have moved.

Error code: 404 Not Found

    The site could be temporarily unavailable or too busy. Try again in a few moments.

My Implementation

Here is the Java method I am using to trigger the download. It’s designed to add the download component, simulate a click, and then clean it up.

private void triggerDownload(StreamResource resource) {
        UI ui = UI.getCurrent();
        if (ui == null || detached.get() || ui.isClosing()) {
            return;
        }

        Button downloadButton = new Button();
        downloadButton.getStyle().set("display", "none"); // Nasconde il pulsante

        FileDownloadWrapper downloadWrapper = new FileDownloadWrapper(resource);
        downloadWrapper.wrapComponent(downloadButton);

        ui.access(() -> {
            this.getContent().add(downloadWrapper);
            // Clicca programmaticamente il pulsante per avviare il download
            downloadButton.getElement().executeJs("this.click()")
                    .then(result -> ui.access(() -> {
                        // Rimuove il wrapper dopo l'avvio del download
                        if (!detached.get()) {
                            this.getContent().remove(downloadWrapper);
                        }
                    }));
        });
    }

What I’ve Considered

  1. Race Condition: My primary suspicion is a race condition. It seems the FileDownloadWrapper is removed from the UI before Firefox has fully initiated the download request for the StreamResource. This could explain why the dynamic resource URL is no longer valid, leading to the 404.
  2. Browser Behavior: The fact that it’s worse with a non-English browser language and specific to Firefox suggests it might be related to how Firefox handles programmatic clicks and navigation compared to other browsers.
  3. Component Lifecycle: I’m trying to manage the component lifecycle correctly by adding the wrapper before the click and removing it after, but maybe there’s a better way to ensure the resource is available until the download has started.

Has anyone encountered a similar issue with FileDownloadWrapper and Firefox? Is there a more robust way to programmatically trigger a download that avoids this potential race condition?

Any advice would be greatly appreciated. Thank you!

You are fighting a battle that you can only lose. Downloads should be initiated by users because of security concerns by all major browser vendors.

Would you share a bit more about your requirements/what you are trying to achieve? I have a hunch that DynamicFileDownloader (from Viritin add-on) is the solution, although there are some browser differences that probably can’t be totally worked around.

There are also similarish framework enhancement coming in the next minor, so if you can share your requirements, it would be great timing to test them against the pre-releases. I’m willing the help there :nerd_face:

We have just discussed DownloadHandler disconnects from UI on Firefox · Issue #21587 · vaadin/flow · GitHub internally. Not necessarily related to your problem, but since you’re using async UI updates, downloads and Firefox, I decided to mention it.

Thank you for the suggestion! To clarify my requirements:

  1. The download is triggered by a user clicking an icon button within a specific row of a Vaadin Grid.

  2. The file to be downloaded (a ZIP with the PDF inside) does not exist beforehand. It is generated on-the-fly on the backend when the user clicks the button.

  3. Both the content of the PDF and its filename are dynamic, based on the data of the selected row in the grid.

  4. While the file is being generated, the UI should remain responsive. The download should start automatically once the file is ready on the server, without navigating away from the page.

My current implementation with FileDownloadWrapper tries to achieve this by programmatically adding, clicking, and then removing the component, but this seems to cause a race condition in Firefox, leading to the intermittent 404 errors.

Given this workflow, do you think DynamicFileDownloader or the upcoming framework enhancements would be a more robust solution?


I generate the zip file like this:

private void executeExport(Scenario scenario, boolean desc, boolean brief, boolean infoGen,
                               boolean patto, boolean azioni, boolean obiettivi, boolean moula, boolean liqui,
                               boolean matNec, boolean param, boolean acces, boolean fisic,
                               boolean esam, boolean time, boolean scen,
                               ZipExportService zipExportService) {
        Notification.show("Generazione del PDF...", 3000, Notification.Position.MIDDLE).addThemeVariants(NotificationVariant.LUMO_PRIMARY);
        try {
            StreamResource resource = new StreamResource(
                    "Pdf_scenario_" + limitLength(sanitizeFileName(scenario.getTitolo())) + ".zip",
                    () -> {
                        try {
                            byte[] pdfBytes = zipExportService.exportScenarioPdfToZip(
                                    scenario.getId(), desc, brief, infoGen, patto,
                                    azioni, obiettivi, moula, liqui, matNec, param, acces,
                                    fisic, esam, time, scen);
                            return new ByteArrayInputStream(pdfBytes);
                        } catch (IOException | RuntimeException e) {
                            System.err.println("Errore generazione PDF per lo scenario " + scenario.getId() + ": " + e.getMessage());
                            getUI().ifPresent(ui -> ui.access(() ->
                                    Notification.show(e.getMessage(), 5000, Notification.Position.MIDDLE)
                                            .addThemeVariants(NotificationVariant.LUMO_ERROR)));
                            return new ByteArrayInputStream(new byte[0]);
                        }
                    }
            );
            resource.setContentType("application/zip");
            triggerDownload(resource);
        } catch (Exception e) {
            handleExportError("Errore preparazione PDF", e);
        }
    }

FileDownloadWrapper relies on a pre-generated StreamResource and is not intended for dynamic downloads.

I didn’t know that, thank you.

Can DynamicFileDownloader be the solution?

Yup, it should be exactly for that! And the upcoming improvements should work as well.