使用Vaadin 14中的“上传”小部件将文本文件的内容上传到内存中的字符串

时间:2019-10-21 20:30:15

标签: java file-upload upload vaadin vaadin-flow

我知道Vaadin 14提供了Upload组件供用户选择要上传的文件或拖放文件。

但是我不确定如何使用它。我希望将网络浏览器计算机上的纯文本文件的内容作为服务器计算机上的StringCharSequence加载到内存中。

虽然该组件的描述页面上有一些示例,但我可以使用一个完整而最少的示例来加载纯文本。

1 个答案:

答案 0 :(得分:2)

这是Vaadin 14.1.0.alpha3中的示例视图。我不是Upload的专家,所以可能有更好的方法,但这似乎行得通。

Screenshot of Vaadin "Upload" component in action.

注意@Route注释,并进行调整以适合您自己的应用。

Upload组件是出现在您的网页上的可视窗口小部件,邀请用户拖放文件或使用文件选择对话框。我们添加了一个匿名侦听器对象(在此用lambda语法定义),当用户这样做时将被调用。 FinishedEvent对象作为要处理的文件传递给我们的侦听器。

接收上载八位位组的对象是Vaadin Receiver接口的任何实现。要将单个文件加载到内存中,请使用MemoryBuffer实现。通过将MemoryBuffer实例传递到我们的Upload实例,我们为上传的八位位组到达服务器时指定了放置位置。

我们使用InputStream来管理到达的八位位组的流。在此示例中,我们一张一张地读取到达的八位位组。另外,还有一些方法可以一起读取许多八位字节。

我们的InputStream将每个八位字节作为int来读取,其值的范围是0-255(包括0-255)。 -1的值表示输入流已结束。因此,我们在int循环中收集这些while值,直到出现负数为止。

我们使用try-with-resources语法来automatically close InputStream,将字节从客户端加载到服务器。

我们在ByteArrayOutputStream中收集到达的八位位组。下一步是弄清那些收集的八位位组。这里没有魔术。您必须知道预期的内容,例如plain text,格式化文本,tab-delimited数据,二进制数据和文档格式,例如PDF。在此示例中,我们希望使用纯文本。对于文本,我们必须知道字符编码,例如ASCIIUTF-8或旧版Windows-1252编码。在我们的情况下,我们希望使用UTF-8编码。因此,我们通过实例化一个新的String对象,将我们的收集八位字节和一个枚举对象传递给构造函数,以表示我们对UTF-8的期望:new String( bytesReceived.toByteArray() , StandardCharsets.UTF_8 )

使用新的String,我们通过实例化HTML段落来向用户回显文件的内容。

这是整个示例类。

package work.basil.example;

import com.vaadin.flow.component.html.H1;
import com.vaadin.flow.component.html.Paragraph;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.upload.FinishedEvent;
import com.vaadin.flow.component.upload.Upload;
import com.vaadin.flow.component.upload.receivers.MemoryBuffer;
import com.vaadin.flow.router.Route;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;

@Route ( "upload" )
public class UploadView extends VerticalLayout
{
    // Constructor
    public UploadView ( )
    {
        this.add( new H1( "Upload" ) );
        MemoryBuffer buffer = new MemoryBuffer();
        Upload upload = new Upload( buffer );  // Connect our server-side `Receiver` implementation to the client-side `Upload` widget.
        upload.addFinishedListener(
                ( FinishedEvent finishedEvent ) -> {  // Event fired when user uses the `Upload` widget on the web page.
                    try (  // Autoclosable interface used in try-with-resources syntax.
                           InputStream inputStream = buffer.getInputStream() ;
                    )
                    {
                        // read the contents of the buffer.
                        // https://www.baeldung.com/convert-input-stream-to-array-of-bytes
                        ByteArrayOutputStream bytesReceived = new ByteArrayOutputStream();
                        int content; // Represents each octet arriving on server from client.
                        while ( ( content = inputStream.read() ) != - 1 )  // The arriving octet is returned to us as an `int` in the range 0 to 255. A value of -1 signals end-of-stream. Blocks until data arrives or stream closes.
                        {
                            bytesReceived.write( content );  // Collect the arriving octets into a `ByteArrayOutputStream`.
                        }
                        // Parse the collected octets as being text in UTF-8 encoding.
                        String s = new String( bytesReceived.toByteArray() , StandardCharsets.UTF_8 );  // You must know the particular  character-encoding used in the file.
                        this.add( new Paragraph( s ) );  // Echo the file contents back to the user.
                        System.out.println( "s = " + s );
                    }
                    catch ( IOException e )
                    {
                        e.printStackTrace();
                    }
                }
        );
        this.add( upload );  // Make the `Upload` instance named `upload` appear on our Vaadin-produced web page.
    }
}

我们可以简化上面的代码。 Vaadin 14.1捆绑了Apache Commons IO 2.5库。该库具有一种方便的方法来获取InputStream并生成String。因此,可以将我们上面的代码块转换为单行代码。调用静态方法org.apache.commons.io.IOUtils.toString。传递输入流,并指定所需的字符编码。

修改后的代码:

package work.basil.example ;

import com.vaadin.flow.component.html.H1;
import com.vaadin.flow.component.html.Paragraph;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.upload.FinishedEvent;
import com.vaadin.flow.component.upload.Upload;
import com.vaadin.flow.component.upload.receivers.MemoryBuffer;
import com.vaadin.flow.router.PreserveOnRefresh;
import com.vaadin.flow.router.Route;
import org.apache.commons.io.IOUtils;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;

@PreserveOnRefresh
@Route ( "upload" )
public class UploadView extends VerticalLayout
{
    // Constructor
    public UploadView ( )
    {
        this.add( new H1( "Upload" ) );
        MemoryBuffer buffer = new MemoryBuffer();
        Upload upload = new Upload( buffer );  // Connect our server-side `Receiver` implementation to the client-side `Upload` widget.
        upload.addFinishedListener(
                ( FinishedEvent finishedEvent ) -> {  // Event fired when user uses the `Upload` widget on the web page.

                    try (  // Autoclosable interface used in try-with-resources syntax.
                           InputStream inputStream = buffer.getInputStream() ;
                    )
                    {
                        // Read the data arriving in the buffer via the `InputStream` to produce a `String` object.
                        String s = IOUtils.toString( inputStream , StandardCharsets.UTF_8 );
                        this.add( new Paragraph( s ) );
                        System.out.println( "s = " + s );
                    }
                    catch ( IOException e )
                    {
                        e.printStackTrace();
                    }
                }
        );
        this.add( upload );  // Make the `Upload` instance named `upload` appear on our Vaadin-produced web page.
    }
}

注意事项:上面的示例是您所要求的基本知识。我们没有进行任何错误处理,也没有对用户取消中途上传做出反应。


您可以通过阅读Vaadin Ltd公司提供的source code of the Upload component’s demo page了解更多信息。

并阅读Matti Tahvonen撰写的有关Vaemin Flow中{em> Upload 的工作原理的详细文章,Uploads and downloads, inputs and outputs