Download with file name defaulting to date-time of user event in Vaadin Flow app

孤街醉人 提交于 2021-01-29 03:00:39

问题


In my Vaadin Flow web app (version 14 or later), I want to present to my user a link that will download a data file to them. The default name of the file to be downloaded should be determined at the moment the user initiates the download.

I am aware of the Anchor widget in Vaadin Flow. With an Anchor, the default name for the downloaded file will be the resource name given in the URL of the link. Unfortunately, that is determined when the page loads rather than later when the user clicks the link. So this approach fails to meet my need to label the download with the date-time captured at the moment the user initiates the download.

String when = Instant.now().toString().replace( "-" , "" ).replace( ":" , "" ); // Use "basic" version of standard ISO 8601 format for date-time.
StreamResource streamResource = new StreamResource( "rows_" + when + ".txt" , ( ) -> this.makeContent() );
Anchor anchor = new Anchor( streamResource , "Download generated data" );

Perhaps the solution would be the use of a Button widget rather than an Anchor. Using a button for dynamically-created content is shown in the manual in the Advanced Topics > Dynamic Content page. Unfortunately, the example there loads a resource on the page rather than doing a download for the user.

➥ Can a Button in Vaadin Flow be used to initiate a download?

➥ Is there some other approach to initiating a download with a URL determined when the user initiates the download rather than when the page loads?


回答1:


Can a Button in Vaadin Flow be used to initiate a download?

Sort of yes, but it requires some client side implementation. There is File Download Wrapper add-on in Directory, which does this. With it is possible to wrap e.g. Button. However I think it will not solve problem of yours fully. I suspect that the setting the filename in click event wont apply (it comes too late). But I do think, that it would be possible to add filename provider callback feature to this add-on.




回答2:


Consider this HACK that simulates a click on a dynamically added Anchor on client-side:

    private void downloadWorkaround(Component anyComponent, int delay) {
        Anchor hiddenDownloadLink = new Anchor(createStreamResource(), "Workaround");
        hiddenDownloadLink.setId("ExportLinkWorkaround_" + System.currentTimeMillis());
        hiddenDownloadLink.getElement().setAttribute("style", "display: none");
        var parent = anyComponent.getParent().orElseThrow();
        var parenthc = (HasComponents) parent;
        for (Component c : parent.getChildren().collect(Collectors.toList())) {
            if (c.getId().orElse("").startsWith("ExportLinkWorkaround_")) {
                // clean up old download link
                parenthc.remove(c);
            }
        }
        parenthc.add(hiddenDownloadLink);
        UI.getCurrent().getPage().executeJs("setTimeout(function(){" + // delay as workaround for bug when dialog open before
                "document.getElementById('" + hiddenDownloadLink.getId().orElseThrow() + "').click();"
                + "}, " + delay + ");"
        );
    }

Call the method on button click event or something. The additional delay is required sometimes. For me the delay was necessary to start the download from a modal dialog OK button that also closed the dialog. But perhaps you don't even need that.

I had no luck with the file download wrapper add-on mentioned by Tatu for my specific use case: I wanted to show a dialog under some circumstances before providing the download to user.



来源:https://stackoverflow.com/questions/60729258/download-with-file-name-defaulting-to-date-time-of-user-event-in-vaadin-flow-app

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!