Upload
- Usage
- Styling
- File Handling
- Drag & Drop
- Auto-Upload
- Upload Restrictions
- File Actions
- Internationalization (i18n)
- Customization
- Listeners
- Best Practices
- Related Components
Upload allows the user to upload files, giving feedback to the user during the upload process. It shows the upload progress and the status of each file. Files can be uploaded by clicking on the Upload button, or by dragging them onto the component.
new tab
MultiFileMemoryBuffer buffer = new MultiFileMemoryBuffer();
Upload upload = new Upload(buffer);
upload.addSucceededListener(event -> {
String fileName = event.getFileName();
InputStream inputStream = buffer.getInputStream(fileName);
// Do something with the file data
// processFile(inputStream, fileName);
});
Drag & Drop
Upload allows the user to drag files onto the component to upload them. Multiple files can be dropped simultaneously. By default, this is enabled on desktop computers, and disabled on touch devices. Explicitly setting it to enabled or disabled, though, affects both desktop and mobile devices.
new tab
Upload dropEnabledUpload = new Upload(buffer1);
dropEnabledUpload.setDropAllowed(true);
Upload dropDisabledUpload = new Upload(buffer2);
dropDisabledUpload.setDropAllowed(false);
Auto-Upload
By default, files are uploaded immediately — or at least they’re added to the queue to be uploaded. Auto-upload can be disabled, for example, to allow the user to review the list of files before initiating their upload by clicking the ▶️ button for each file. Change the button label, though, to indicate that uploads don’t start automatically.
new tab
Upload upload = new Upload(buffer);
upload.setAutoUpload(false);
UploadExamplesI18N i18n = new UploadExamplesI18N();
i18n.getAddFiles().setMany("Select Files...");
upload.setI18n(i18n);
Uploads can be initiated programmatically when auto-upload is disabled. You might do this, for example, if you want to provide the user with a single button to start all uploads.
new tab
Upload upload = new Upload(buffer);
upload.setAutoUpload(false);
Button uploadAllButton = new Button("Upload All Files");
uploadAllButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
uploadAllButton.addClickListener(event -> {
// No explicit Flow API for this at the moment
upload.getElement().callJsFunction("uploadFiles");
});
Upload Restrictions
You can set three types of restrictions: file format; file count; and file size.
Exceptions that arise — usually from the user violating any of the imposed restrictions — aren’t shown in the UI by default. Use a File Rejected listener to catch those exceptions and, for example, a Notification to inform the user of the problem, together with any potential solutions.
The user should be informed upfront, though, about any file upload restrictions. Limitations on the maximum number of files allowed, file size, and format should all be communicated clearly, to reduce or eliminate exceptions.
File Format
Upload can be configured to accept only files of specific formats. The acceptable file formats are set using MIME type patterns or file extensions (e.g., "video/*"
, "image/tiff"
or ".pdf"
and "audio/mp3"
).
new tab
Upload upload = new Upload(buffer);
upload.setAcceptedFileTypes("application/pdf", ".pdf");
upload.addFileRejectedListener(event -> {
String errorMessage = event.getErrorMessage();
Notification notification = Notification.show(errorMessage, 5000,
Notification.Position.MIDDLE);
notification.addThemeVariants(NotificationVariant.LUMO_ERROR);
});
Note
|
Prefer MIME Type
Although MIME types are widely supported, file extensions are only implemented in certain browsers and should be avoided.
|
Note
|
File Format Restrictions are Client-Side
File format restrictions set with Using this method won’t restrict the uploaded file’s format on the server side. The Upload component doesn’t have an API to restrict uploaded files by file format or content on the server side. If required, it’s the responsibility of the application developer to implement application-specific restrictions on the server side in one or more of the Upload component’s event listeners (e.g., in |
File Count
By default, Upload doesn’t limit the number of files that can be uploaded. However, you can set a file count limit. If you set the maximum to one, the native file browser prevents multiple files from being selected.
Note
|
Java Flow-Specific
When using a Receiver that doesn’t implement the MultiFileReceiver interface — such as MemoryBuffer or FileBuffer — the Upload component limits the number of files to one. This is because these receiver implementations only support handling a single file at once.
|
new tab
Upload upload = new Upload(buffer);
upload.setMaxFiles(3);
upload.addFileRejectedListener(event -> {
String errorMessage = event.getErrorMessage();
Notification notification = Notification.show(errorMessage, 5000,
Notification.Position.MIDDLE);
notification.addThemeVariants(NotificationVariant.LUMO_ERROR);
});
File Size
Upload allows you to limit the file size by setting a maximum amount in bytes. By default, though, there is no limit.
new tab
Upload upload = new Upload(buffer);
int maxFileSizeInBytes = 10 * 1024 * 1024; // 10MB
upload.setMaxFileSize(maxFileSizeInBytes);
upload.addFileRejectedListener(event -> {
String errorMessage = event.getErrorMessage();
Notification notification = Notification.show(errorMessage, 5000,
Notification.Position.MIDDLE);
notification.addThemeVariants(NotificationVariant.LUMO_ERROR);
});
Note
|
Revalidate Size Limit on Server
This constraint is set on the client and is checked before contacting the server.
|
File Actions
Each file has a certain set of associated actions available, depending on its upload state. A file always has a Clear/Remove button. This button cancels the upload if applicable, and removes the file from the list. This button is the only available action during and after a successful upload.
new tab
import React from 'react';
import { useComputed } from '@vaadin/hilla-react-signals';
import { Upload } from '@vaadin/react-components/Upload.js';
import { createFakeUploadFiles } from './upload-demo-helpers';
function createFakeFiles() {
return createFakeUploadFiles([
{
name: 'Workflow.pdf',
progress: 60,
status: '19.7 MB: 60% (remaining time: 00:12:34)',
},
{ name: 'Financials.xlsx', complete: true },
]);
}
function Example() {
const files = useComputed(createFakeFiles);
return <Upload files={files.value} />;
}
Note
|
Remove the File
The Clear/Remove button doesn’t remove a successfully uploaded file from the server file system or database. It’s only removed from the file list. Remember to remove the file from the backend.
|
If an error or exception occurs, Upload displays a Retry button for the user to be able to try to upload the file again.
When a file is queued (i.e., auto-upload is disabled), there’s a Start Button that the user must press to begin the upload process.
Internationalization (i18n)
All labels and messages in Upload are configurable. For a complete list of them, see the API documentation (Java and Web component).
new tab
Upload upload = new Upload(buffer);
// See the separate UploadFinnishI18N class / file
// in this example for the I18N configuration
UploadFinnishI18N i18N = new UploadFinnishI18N();
upload.setI18n(i18N);
Customization
You can replace the default upload button. You might do this if Upload needs a stronger emphasis. If so, you can use a primary button.
new tab
Upload upload = new Upload(buffer);
upload.setAcceptedFileTypes("application/pdf", ".pdf");
Button uploadButton = new Button("Upload PDF...");
uploadButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
upload.setUploadButton(uploadButton);
// Disable the upload button after the file is selected
// Re-enable the upload button after the file is cleared
upload.getElement()
.addEventListener("max-files-reached-changed", event -> {
boolean maxFilesReached = event.getEventData()
.getBoolean("event.detail.value");
uploadButton.setEnabled(!maxFilesReached);
}).addEventData("event.detail.value");
You can also customize the drop label, as well as the icon.
new tab
Upload upload = new Upload(buffer);
Span dropLabel = createDropLabel();
Icon dropIcon = VaadinIcon.CLOUD_UPLOAD_O.create();
upload.setDropLabel(dropLabel);
upload.setDropLabelIcon(dropIcon);
Tip
|
Large Drop Target
When customizing the Upload component, make sure not to make the drop target too small. A large drop target is easier to use and less error-prone.
|
Listeners
Upload has listeners for the following events:
- All Finished
-
Triggered when Upload has processed all of the files in its queue, regardless of whether all uploads were successful.
- Failed
-
Occurs when the upload is received, but the reception is interrupted for some reason.
- File Rejected
-
Sent when the file selected for upload doesn’t meet the constraints (e.g., file size limit).
- Finished
-
Sent when Upload receives a file, regardless of whether the upload was successful. To distinguish results, use instead either Succeeded or Failed listeners.
- Progress
-
Event for tracking upload progress.
- Started
-
Triggered when the upload starts.
- Succeeded
-
Sent when the upload has been received successfully.
Best Practices
With regards to developing with Upload, this section provides some suggestions on how to label buttons and how to construct error messages for better user experiences.
Labeling
Choose labels that are informative and instructive. For example, if the user is to upload a single PDF file, it’s better to have the button label say "Upload PDF…" instead of "Upload File…". The task becomes clearer and improves accessibility for the user — especially if they’re using a screen reader, as the button’s label is read aloud when focused.
new tab
Upload upload = new Upload(buffer);
upload.setAcceptedFileTypes("application/pdf", ".pdf");
UploadExamplesI18N i18n = new UploadExamplesI18N();
i18n.getAddFiles().setOne("Upload PDF...");
i18n.getDropFiles().setOne("Drop PDF here");
i18n.getError().setIncorrectFileType(
"The provided file does not have the correct format (PDF document).");
upload.setI18n(i18n);
Likewise, if the user is expected to upload a spreadsheet, but multiple file formats are accepted, label the button, "Upload Spreadsheet". Include helpers to inform the user which formats are accepted.
new tab
H4 title = new H4("Upload spreadsheet");
Paragraph hint = new Paragraph(
"File size must be less than or equal to 1 MB. Only Excel and CSV files are accepted.");
Upload upload = new Upload(buffer);
upload.setAcceptedFileTypes(
// Microsoft Excel (.xls)
"application/vnd.ms-excel", ".xls",
// Microsoft Excel (OpenXML, .xlsx)
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
".xlsx",
// Comma-separated values (.csv)
"text/csv", ".csv");
UploadExamplesI18N i18n = new UploadExamplesI18N();
i18n.getAddFiles().setOne("Upload Spreadsheet...");
i18n.getDropFiles().setOne("Drop spreadsheet here");
i18n.getError().setIncorrectFileType(
"Provide the file in one of the supported formats (.xls, .xlsx, .csv).");
upload.setI18n(i18n);
add(title, hint, upload);
Error Messages
Try to provide meaningful feedback and error messages when an exception or error occurs. Avoid technical jargon. Instead, try to provide solutions and instructions on how to fix the error.
A "Server Unavailable" message might suffice for tech-savvy users, but for some it might be lacking, unhelpful, and frustrating. Error messages should be written with your users in mind.
new tab
Upload upload = new Upload(buffer);
upload.setDropAllowed(false);
UploadExamplesI18N i18N = new UploadExamplesI18N();
i18N.getUploading().getError().setUnexpectedServerError(
"File couldn't be uploaded, please try again later");
upload.setI18n(i18N);