Skip to content

Instantly share code, notes, and snippets.

@TatuLund
Created November 9, 2023 09:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save TatuLund/986114a82078e7228b1c37ba4b07f94d to your computer and use it in GitHub Desktop.
Save TatuLund/986114a82078e7228b1c37ba4b07f94d to your computer and use it in GitHub Desktop.
Vaadin 14/23/24 Upload component does not yet have good Java API for removing files server side. This example shows a workaround how to detect file remove button event and use it to remove matching component according to file na,e.
package com.example.application.views;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import org.apache.commons.io.IOUtils;
import com.vaadin.flow.component.ClientCallable;
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.ComponentUtil;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.html.Image;
import com.vaadin.flow.component.notification.Notification;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.upload.Upload;
import com.vaadin.flow.component.upload.receivers.MultiFileMemoryBuffer;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.server.StreamResource;
import elemental.json.JsonValue;
@Route(value = "upload", layout = MainLayout.class)
public class UploadView extends VerticalLayout {
private Div output;
// This is called from JavaScript event listener, compare file name
// to piggy bagged file names and remove if match
@ClientCallable
public void fileRemove(JsonValue event) {
output.getChildren()
.filter(component -> event.toJson().contains(
(String) ComponentUtil.getData(component, "name")))
.findFirst().ifPresent(match -> output.remove(match));
}
public UploadView() {
output = new Div();
MultiFileMemoryBuffer buffer = new MultiFileMemoryBuffer();
Upload upload = new Upload(buffer);
upload.setSizeFull();
upload.addFileRejectedListener(event -> {
Notification.show(event.getErrorMessage());
});
upload.setAcceptedFileTypes("image/jpeg");
upload.addSucceededListener(event -> {
Component component = createComponent(event.getFileName(),
buffer.getInputStream(event.getFileName()));
output.add(component);
});
// using
// reg = upload.getElement().addEventListener("file-remove" ...
// reg.addEventData("event.detail");
// does not work here, as the file.name is not included in event data
// thus we need to wire event listener in JavaScript and call client
// callable method
upload.getElement().executeJs(
"this.addEventListener('file-remove', (e) => $0.$server.fileRemove(e.detail.file.name));",
getElement());
add(upload, output);
}
private Component createComponent(String fileName, InputStream stream) {
Image image = new Image();
try {
byte[] bytes = IOUtils.toByteArray(stream);
image.getElement().setAttribute("src", new StreamResource(fileName,
() -> new ByteArrayInputStream(bytes)));
try (ImageInputStream in = ImageIO
.createImageInputStream(new ByteArrayInputStream(bytes))) {
final Iterator<ImageReader> readers = ImageIO
.getImageReaders(in);
if (readers.hasNext()) {
ImageReader reader = readers.next();
try {
reader.setInput(in);
image.setWidth("300px");
} finally {
reader.dispose();
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
// Piggy bag name of the file to the component
ComponentUtil.setData(image, "name", fileName);
return image;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment