Skip to content

Commit eaa82b2

Browse files
committed
fix: avoid serializing full File instance for determining uploading state (#9444) (CP: 25.1)
1 parent 822f831 commit eaa82b2

2 files changed

Lines changed: 58 additions & 17 deletions

File tree

  • vaadin-upload-flow-parent
    • vaadin-upload-flow-integration-tests/src/test/java/com/vaadin/flow/component/upload/tests
    • vaadin-upload-flow/src/main/java/com/vaadin/flow/component/upload

vaadin-upload-flow-parent/vaadin-upload-flow-integration-tests/src/test/java/com/vaadin/flow/component/upload/tests/UploadIT.java

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,58 @@ public void uploadFileAndNoErrorThrown() throws Exception {
179179
logList2.size());
180180
}
181181

182+
@Test
183+
public void multipleFiles_oneStillUploading_allFinishedNotFiredYet()
184+
throws Exception {
185+
UploadElement upload = getUpload();
186+
187+
// Disable auto upload so the files can be uploaded one at a time.
188+
upload.setProperty("noAuto", true);
189+
190+
// Add two files. Mark them as uploading in order to be able to test
191+
// that all-finished event is not fired until both files have succeeded
192+
// uploading.
193+
upload.upload(createTempFile("txt"), 0);
194+
upload.upload(createTempFile("txt"), 0);
195+
executeScript(
196+
"arguments[0].files.forEach(file => { file.uploading = true });",
197+
upload);
198+
199+
// Upload the first file by pressing its manual upload start button.
200+
startUploadOfFile(upload, 0);
201+
202+
// Wait for the first file to finish uploading.
203+
waitUntil(driver -> eventsOutput.getText().contains("-succeeded"));
204+
205+
// The second file is still uploading, so the all-finished event must
206+
// not have fired yet.
207+
Assert.assertEquals(
208+
"All-finished event must not fire while another file is "
209+
+ "still uploading",
210+
"-succeeded", eventsOutput.getText());
211+
212+
// Upload the second file by pressing its manual upload start button.
213+
startUploadOfFile(upload, 1);
214+
215+
// All files have finished now, so the all-finished event must fire.
216+
waitUntil(driver -> "-succeeded-succeeded-finished"
217+
.equals(eventsOutput.getText()));
218+
}
219+
220+
private void startUploadOfFile(UploadElement upload, int index) {
221+
// Clear the uploading flag on the file and re-render the file list so
222+
// the start button becomes available
223+
executeScript("""
224+
const upload = arguments[0];
225+
const fileIndex = arguments[1];
226+
upload.files[fileIndex].uploading = false;
227+
upload.files = [...upload.files];
228+
""", upload, index);
229+
WebElement startButton = upload.$("vaadin-upload-file").get(index)
230+
.$("*").withAttribute("part", "start-button").single();
231+
startButton.click();
232+
}
233+
182234
@Test
183235
public void slowUpload_waitForUpload_pollsUntilUploadFinishes()
184236
throws Exception {

vaadin-upload-flow-parent/vaadin-upload-flow/src/main/java/com/vaadin/flow/component/upload/Upload.java

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
import java.util.Deque;
2222
import java.util.List;
2323
import java.util.Objects;
24-
import java.util.stream.IntStream;
2524

2625
import com.vaadin.flow.component.Component;
2726
import com.vaadin.flow.component.ComponentEventListener;
@@ -50,9 +49,6 @@
5049
import com.vaadin.flow.server.streams.UploadHandler;
5150
import com.vaadin.flow.shared.Registration;
5251

53-
import tools.jackson.databind.JsonNode;
54-
import tools.jackson.databind.node.ArrayNode;
55-
5652
/**
5753
* Upload is a component for uploading one or more files. It shows the upload
5854
* progression and status of each file. Files can be uploaded using the Upload
@@ -130,17 +126,10 @@ public Upload() {
130126

131127
setUploadHandler(new FailFastUploadHandler());
132128

133-
final String elementFiles = "element.files";
129+
final String filesUploading = "element.files.some(file => file.uploading)";
134130
DomEventListener allFinishedListener = e -> {
135-
ArrayNode files = (ArrayNode) e.getEventData().get(elementFiles);
136-
137-
boolean isUploading = IntStream.range(0, files.size())
138-
.anyMatch(index -> {
139-
final String KEY = "uploading";
140-
JsonNode object = files.get(index);
141-
return object.has(KEY)
142-
&& object.get(KEY).booleanValue();
143-
});
131+
boolean isUploading = e.getEventData().get(filesUploading)
132+
.booleanValue();
144133

145134
if (this.uploading && !isUploading) {
146135
this.fireAllFinish();
@@ -152,11 +141,11 @@ public Upload() {
152141
e -> this.uploading = true);
153142

154143
getElement().addEventListener("upload-success", allFinishedListener)
155-
.addEventData(elementFiles);
144+
.addEventData(filesUploading);
156145
getElement().addEventListener("upload-error", allFinishedListener)
157-
.addEventData(elementFiles);
146+
.addEventData(filesUploading);
158147
getElement().addEventListener("upload-abort", allFinishedListener)
159-
.addEventData(elementFiles);
148+
.addEventData(filesUploading);
160149

161150
defaultUploadButton = new Button();
162151
// Ensure the flag is set before the element is added to the slot

0 commit comments

Comments
 (0)