动态创建的内容,无需在Vaadin Flow Web应用程序的服务器端写入文件即可下载,而无需下载文件

问题描述 投票:0回答:1

在我的Vaadin Flow网络应用程序(版本14或更高版本)中,我想向我的用户显示下载数据文件的链接。

此下载内容可能很大。因此,我不想一次全部实现内存中的全部内容。我想连续产生大量的内容,一次提供一个下载块,以最大程度地减少内存的使用。例如,想象一下,数据库中有很多行,我们一次将一行送入下载。

我知道Vaadin Flow中的Anchor小部件。但是,如何将一些动态创建的内容挂接到此类小部件?

此外,鉴于此数据是动态动态生成的,因此我希望用户计算机上已下载文件的名称默认为某个前缀,后跟YYYYMMDDTHHMMSS格式的当前日期时间。

java download vaadin dynamically-generated vaadin-flow
1个回答
0
投票

注意:在这件事上我不是专家。我在这里提供的示例代码似乎运行正常。通过研究有限的文档并阅读了网络上的许多其他文章,我将这种解决方案拼凑在一起。矿山可能不是最好的解决方案。


有关更多信息,请参见Vaadin手册的Anchor页面。

我们在您的问题中有三大部分:

  • Vaadin Web应用程序页面上的小部件,可为用户提供下载。
  • 动态内容创建者
  • 在用户计算机上创建的文件的默认名称

下载小部件

如问题中所述,我们确实使用了Dynamic Content小部件(请参阅Anchor)。

我们在布局上定义一个成员变量。

Javadoc

我们通过传递private Anchor anchor; 对象实例化。此类在Vaadin中定义。它的工作是包装我们制作的类,该类将产生扩展Java类StreamResource的实现。

输入流通过从其StreamResource方法返回一个InputStream来一次提供一个八位位组的数据,其值是所需八位位组的数字,即0-255。到达数据末尾时,InputStream返回负数。

在我们的代码中,我们已经实现了一个read方法来充当int工厂。

read

[实例化我们的makeStreamOfContent时,我们传递了一个引用该InputStream方法的方法引用。由于没有输入流或任何数据尚未生成,因此我们在这里变得有点抽象。我们只是在准备舞台;该操作稍后发生。

传递给private InputStream makeInputStreamOfContent ( ) { return GenerativeInputStream.make( 4 ); } 的第一个参数是要在用户客户端计算机上创建的文件的默认名称。在此示例中,我们使用的是StreamResource的虚构名称。

makeInputStreamOfContent

接下来,我们在HTML5 new StreamResource元素上设置report.text的属性。此属性向浏览器指示当用户单击链接时我们打算下载目标。

anchor = 
    new Anchor( 
        new StreamResource( "report.text" , this :: makeInputStreamOfContent ) , 
        "Download generated content" 
    )
;

您可以通过将锚点控件包装在download中来显示图标。

download

如果使用这样的图标,则应从anchor小部件中删除文本标签。而是将任何所需的文本放在anchor.getElement().setAttribute( "download" , true ); 中。因此,我们将空字符串(Button)传递给Button,并将标签文本作为第一个参数传递给downloadButton = new Button( new Icon( VaadinIcon.DOWNLOAD_ALT ) ); anchor.add( downloadButton );

Anchor

动态内容创建者

我们需要实现一个Button子类,以提供给我们的下载小部件。

""抽象类提供了除其中一种方法外的所有方法的实现。我们只需要实现new Anchor方法即可满足我们项目的需求。

这里是一种可能的实现方式。实例化new Button对象时,传递要生成的行数。一次生成一行数据,然后逐个八位字节地将数据提供给客户端。完成该行后,将生成另一行。因此,我们一次只处理一行就可以节省内存。

馈给客户端的八位位组是构成我们行的anchor = new Anchor( new StreamResource( "report.text" , this :: makeInputStreamOfContent ) , "" ) ; anchor.getElement().setAttribute( "download" , true ); downloadButton = new Button( "Download generated content" , new Icon( VaadinIcon.DOWNLOAD_ALT ) ) ; anchor.add( downloadButton ); 文本的八位位组。预期文本的每个字符都可以包含一个或多个八位字节。如果您不明白这一点,请阅读Joel Spolsky的有趣且内容丰富的文章InputStream

InputStream

默认文件名

我找不到完成最后一部分的方法,默认文件名包含生成内容的那一刻。

我什至在此发表了关于堆栈溢出的问题:InputStream

问题是,在加载页面并实例化read小部件时,链接小部件背后的URL仅创建了一次。之后,在用户阅读页面时,时间流逝。当用户最终单击链接以开始下载时,当前时刻晚于URL中记录的时刻。

似乎没有简单的方法可以将该URL更新到用户的click事件或download事件的当前时刻。

提示

顺便说一句,对于实际工作,我自己不会写导出的文件。我会改用read之类的库来编写GenerativeInputStreamUTF-8内容。

© www.soinside.com 2019 - 2024. All rights reserved.