Vaadin 23中的文件下载

huangapple go评论65阅读模式
英文:

File download in Vaadin 23

问题

我在Wildfly服务器上运行着一个Vaadin 23应用程序。我想要添加一个按钮,然后开始下载位于web-inf目录下的文件。我只找到了这篇博客文章,似乎已经过时。

哪种方法是最佳(首选)方式来实现这一目标?

谢谢和顺祝
Matt

英文:

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

答案1

得分: 1

一种方法是将文件作为资源获取,并将其设置为“Anchor”。然后,您可以有一个以编程方式单击“Anchor”的“Button”。

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

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

Vaadin的目录中还有一个插件,用于打包上述过程。

请注意,如果您想在对话框中添加“下载”按钮,请确保“Anchor”不在对话框中,参见另一个问题

您还可以在这里找到更完整的下载示例。

英文:

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.

答案2

得分: 0

这是我提出的方法:

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("文件成功传输到%s。", downloadPath.toString());
            showStatusMessage(message, null, MessageStatus.SUCCESS);
            downloadButton.setEnabled(true);
        } catch (IOException exception) {
            // 处理IO异常
        } finally {
            try {
                if (writeChannel != null){
                    writeChannel.close();
                }
                readChannel.close();
            } catch (IOException e) {
                // 处理IO异常
            }
        }
    });
}

问题在于没有对用户询问文件存储位置的对话框,因此这里的JavaScript解决方案非常巧妙。

英文:

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.

huangapple
  • 本文由 发表于 2023年7月13日 22:21:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/76680445.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定