Skip to content
This repository was archived by the owner on May 5, 2021. It is now read-only.

Commit b5bcd46

Browse files
SORMAS-Foundation#2328 Constrain upload size (50MB), buffer output stream, log exceptions
1 parent 929103b commit b5bcd46

2 files changed

Lines changed: 66 additions & 16 deletions

File tree

sormas-ui/src/main/java/de/symeda/sormas/ui/document/DocumentListComponent.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@
2828
import com.vaadin.ui.HorizontalLayout;
2929
import com.vaadin.ui.Label;
3030
import com.vaadin.ui.Notification;
31+
import com.vaadin.ui.Upload;
3132
import com.vaadin.ui.VerticalLayout;
3233
import com.vaadin.ui.themes.ValoTheme;
33-
import com.vaadin.v7.ui.Upload;
3434

3535
import de.symeda.sormas.api.FacadeProvider;
3636
import de.symeda.sormas.api.ReferenceDto;
@@ -96,11 +96,10 @@ private Button buildUploadButton() {
9696
uploadLayout.setWidth(250, Unit.PIXELS);
9797

9898
DocumentReceiver receiver = new DocumentReceiver(relatedEntityType, entityRef.getUuid(), this::reload);
99-
@SuppressWarnings("deprecation")
10099
Upload upload = new Upload("", receiver);
100+
receiver.setUpload(upload);
101101
upload.setButtonCaption(I18nProperties.getCaption(Captions.importImportData));
102102
CssStyles.style(upload, CssStyles.VSPACE_2);
103-
upload.addSucceededListener(receiver);
104103

105104
uploadLayout.addComponentsAndExpand(upload);
106105

sormas-ui/src/main/java/de/symeda/sormas/ui/importer/DocumentReceiver.java

Lines changed: 64 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,24 @@
1414
*/
1515
package de.symeda.sormas.ui.importer;
1616

17+
import java.io.BufferedOutputStream;
1718
import java.io.ByteArrayOutputStream;
1819
import java.io.File;
19-
import java.io.FileNotFoundException;
20-
import java.io.FileOutputStream;
2120
import java.io.IOException;
2221
import java.io.OutputStream;
2322
import java.nio.file.Files;
2423
import java.nio.file.Paths;
2524
import java.util.Date;
2625

26+
import org.slf4j.Logger;
27+
import org.slf4j.LoggerFactory;
28+
2729
import com.vaadin.server.Page;
2830
import com.vaadin.ui.Label;
2931
import com.vaadin.ui.Notification;
30-
import com.vaadin.v7.ui.Upload;
32+
import com.vaadin.ui.Upload;
33+
import com.vaadin.ui.Upload.FailedEvent;
34+
import com.vaadin.ui.Upload.StartedEvent;
3135

3236
import de.symeda.sormas.api.FacadeProvider;
3337
import de.symeda.sormas.api.document.DocumentDto;
@@ -41,13 +45,18 @@
4145
import de.symeda.sormas.ui.UserProvider;
4246
import de.symeda.sormas.ui.utils.VaadinUiUtil;
4347

44-
@SuppressWarnings("deprecation")
45-
public class DocumentReceiver implements com.vaadin.v7.ui.Upload.Receiver, com.vaadin.v7.ui.Upload.SucceededListener {
48+
public class DocumentReceiver
49+
implements Upload.Receiver, Upload.StartedListener, Upload.ProgressListener, Upload.SucceededListener, Upload.FailedListener {
50+
51+
private static final long serialVersionUID = 1L;
52+
private static final long MAX_CONTENT_LENGTH = 52_428_800L;
4653

54+
private final Logger logger = LoggerFactory.getLogger(getClass());
4755
private final DocumentRelatedEntityType relatedEntityType;
4856
private final String relatedEntityUuid;
4957
private final Runnable callback;
5058
private File file;
59+
private Upload upload;
5160

5261
public DocumentReceiver(DocumentRelatedEntityType relatedEntityType, String relatedEntityUuid, Runnable callback) {
5362
this.relatedEntityType = relatedEntityType;
@@ -57,7 +66,6 @@ public DocumentReceiver(DocumentRelatedEntityType relatedEntityType, String rela
5766

5867
@Override
5968
public OutputStream receiveUpload(String fileName, String mimeType) {
60-
final FileOutputStream fos;
6169
// Reject empty files
6270
if (fileName == null || fileName.isEmpty()) {
6371
file = null;
@@ -73,10 +81,12 @@ public OutputStream receiveUpload(String fileName, String mimeType) {
7381
try {
7482
String newFileName = ImportExportUtils.TEMP_FILE_PREFIX + "_document_upload" + DateHelper.formatDateForExport(new Date()) + "_"
7583
+ DataHelper.getShortUuid(UserProvider.getCurrent().getUuid());
76-
file = new File(Paths.get(FacadeProvider.getConfigFacade().getTempFilesPath()).resolve(newFileName).toString());
77-
fos = new FileOutputStream(file);
78-
} catch (FileNotFoundException e) {
79-
file = null;
84+
file = Paths.get(FacadeProvider.getConfigFacade().getTempFilesPath()).resolve(newFileName).toFile();
85+
return new BufferedOutputStream(Files.newOutputStream(file.toPath()));
86+
87+
} catch (IOException e) {
88+
deleteFile();
89+
logger.error(e.getMessage(), e);
8090
new Notification(
8191
I18nProperties.getString(Strings.headingImportError),
8292
I18nProperties.getString(Strings.messageImportError),
@@ -85,12 +95,28 @@ public OutputStream receiveUpload(String fileName, String mimeType) {
8595
// Workaround because returning null here throws an uncatchable UploadException
8696
return new ByteArrayOutputStream();
8797
}
98+
}
8899

89-
return fos;
100+
@Override
101+
public void uploadStarted(StartedEvent event) {
102+
if (event.getContentLength() > MAX_CONTENT_LENGTH) {
103+
event.getUpload().interruptUpload();
104+
new Notification(I18nProperties.getString(Strings.headingImportFailed), "", Notification.Type.ERROR_MESSAGE, false)
105+
.show(Page.getCurrent());
106+
}
107+
}
108+
109+
@Override
110+
public void updateProgress(long readBytes, long contentLength) {
111+
if (contentLength < 0 && Math.max(readBytes, contentLength) > MAX_CONTENT_LENGTH) {
112+
upload.interruptUpload();
113+
new Notification(I18nProperties.getString(Strings.headingImportFailed), "", Notification.Type.ERROR_MESSAGE, false)
114+
.show(Page.getCurrent());
115+
}
90116
}
91117

92118
@Override
93-
public void uploadSucceeded(com.vaadin.v7.ui.Upload.SucceededEvent succeededEvent) {
119+
public void uploadSucceeded(Upload.SucceededEvent succeededEvent) {
94120
if (file == null) {
95121
return;
96122
}
@@ -108,13 +134,20 @@ public void uploadSucceeded(com.vaadin.v7.ui.Upload.SucceededEvent succeededEven
108134
if (ok) {
109135
FacadeProvider.getDocumentFacade().deleteDocument(existing);
110136
saveDocument(succeededEvent);
137+
} else {
138+
deleteFile();
111139
}
112140
});
113141
} else {
114142
saveDocument(succeededEvent);
115143
}
116144
}
117145

146+
@Override
147+
public void uploadFailed(FailedEvent event) {
148+
deleteFile();
149+
}
150+
118151
private void saveDocument(Upload.SucceededEvent succeededEvent) {
119152
try {
120153
DocumentDto document = DocumentDto.build();
@@ -133,8 +166,26 @@ private void saveDocument(Upload.SucceededEvent succeededEvent) {
133166
I18nProperties.getString(Strings.headingUploadSuccess),
134167
I18nProperties.getString(Strings.messageUploadSuccessful));
135168
} catch (IOException | IllegalArgumentException e) {
136-
new Notification(I18nProperties.getString(Strings.headingImportFailed), e.getMessage(), Notification.Type.ERROR_MESSAGE, false)
169+
logger.error(e.getMessage(), e);
170+
new Notification(I18nProperties.getString(Strings.headingImportFailed), "", Notification.Type.ERROR_MESSAGE, false)
137171
.show(Page.getCurrent());
172+
} finally {
173+
deleteFile();
138174
}
139175
}
176+
177+
private void deleteFile() {
178+
if (file != null) {
179+
file.delete();
180+
file = null;
181+
}
182+
}
183+
184+
public void setUpload(Upload upload) {
185+
this.upload = upload;
186+
upload.addStartedListener(this);
187+
upload.addProgressListener(this);
188+
upload.addSucceededListener(this);
189+
upload.addFailedListener(this);
190+
}
140191
}

0 commit comments

Comments
 (0)