2

I want to add an upload button to my web application. In the HTML template, I added:

<link rel="import" href="../../../bower_components/vaadin-upload/src/vaadin-upload.html">

<h2 id="header-Upload">Upload</h2>
<vaadin-upload nodrop/>

I now want to receive the stream in my backend Vaadin process. This stream can be then inserted in the database.

The documentation on https://vaadin.com/components/vaadin-upload/html-examples/upload-basic-demos doesn't provide this information.

I believe I should somehow link a StreamReceiver to the <vaadin-upload> in question, but I am not sure how to do that.

I am using Vaadin Flow (version 12).

Additional information

I tried the following:

In HTML:

<vaadin-upload id="upload" nodrop/>

In Java:

public class MyView extends PolymerTemplate<Model> {
    private final MemoryBuffer buffer = new MemoryBuffer();
    @Id("upload")
    private final Upload       upload = new Upload(buffer);

    public MyView() {
        upload.addSucceededListener(event -> {
            System.out.println(event.getFileName());
            System.out.println(buffer.getInputStream());
        });
    }
}

When I upload a file, I get the following exception:

[qtp162821120-20] ERROR com.vaadin.flow.server.DefaultErrorHandler - 
com.vaadin.flow.server.UploadException: Upload failed
    at com.vaadin.flow.server.communication.StreamReceiverHandler.streamToReceiver(StreamReceiverHandler.java:429)

Caused by: java.lang.IllegalStateException: Upload cannot be performed without a receiver set
    at com.vaadin.flow.component.upload.Upload$DefaultStreamVariable.getOutputStream(Upload.java:581)
    at com.vaadin.flow.server.communication.StreamReceiverHandler.streamToReceiver(StreamReceiverHandler.java:358)
4

2 回答 2

4

massive Edit: The actual solution to your problem was that you instantiated the Upload in your java class, when you should let Vaadin do this (because of the polymer template) and refer to this upload component using an identifier both in the html template (<vaadin-upload id="upload" nodrop/>) as well as in the java code (@Id("upload") private Upload upload;). You can now set the receiver of the upload in the java class using upload.setReceiver(buffer);.

public class MyView implements PolymerTemplate<Model> {

    @Id("upload") // com.vaadin.flow.component.polymertemplate
    private Upload upload; // NO INSTANTIATION!
    private private final MemoryBuffer buffer = new MemoryBuffer();

    public MyView (){
        upload.setReceiver(buffer);
        upload.addSucceededListener(event -> {
            System.out.println(event.getFileName());
            System.out.println(buffer.getInputStream());
        });
    }
}

My initial answer was using an unnecessary alternative approach that was not related to your problem (I thought so at first), but helped finding the real solution.

于 2019-01-23T10:58:03.040 回答
2

The best solution depends a bit about your context, mainly how does your backend accept the data? Does it accept inputstream where it can read the data, does it provide you an outputstream where to write it or is there a simple byte[] where to buffer the content.

If you are using Binder in your form, you could use ByteArrayUploadField from Viritin add-on, which directly binds to byte[] type that you probably have in your domain object.

I recently wrote an article that explains the functionality of Vaadin Upload component. Check that for more details.

于 2019-01-23T11:18:59.823 回答