From a304cf1b618bd2b3d242904dd6ffff4905ad9d91 Mon Sep 17 00:00:00 2001 From: Matthew Horridge Date: Fri, 14 Jun 2024 08:44:46 -0700 Subject: [PATCH 1/2] Reimplementation of multipart file upload --- .../project/CreateNewProjectPresenter.java | 47 +++++++-------- .../client/upload/FileUploadErrorHandler.java | 11 ++++ .../upload/FileUploadSuccessHandler.java | 11 ++++ .../web/client/upload/FileUploader.java | 58 +++++++++++++++++++ .../upload/UploadFileDialogController.java | 58 ++++++------------- 5 files changed, 122 insertions(+), 63 deletions(-) create mode 100644 webprotege-gwt-ui-client/src/main/java/edu/stanford/bmir/protege/web/client/upload/FileUploadErrorHandler.java create mode 100644 webprotege-gwt-ui-client/src/main/java/edu/stanford/bmir/protege/web/client/upload/FileUploadSuccessHandler.java create mode 100644 webprotege-gwt-ui-client/src/main/java/edu/stanford/bmir/protege/web/client/upload/FileUploader.java diff --git a/webprotege-gwt-ui-client/src/main/java/edu/stanford/bmir/protege/web/client/project/CreateNewProjectPresenter.java b/webprotege-gwt-ui-client/src/main/java/edu/stanford/bmir/protege/web/client/project/CreateNewProjectPresenter.java index 2a96e4bf2..5071b83e1 100644 --- a/webprotege-gwt-ui-client/src/main/java/edu/stanford/bmir/protege/web/client/project/CreateNewProjectPresenter.java +++ b/webprotege-gwt-ui-client/src/main/java/edu/stanford/bmir/protege/web/client/project/CreateNewProjectPresenter.java @@ -7,10 +7,12 @@ import edu.stanford.bmir.protege.web.client.dispatch.ProgressDisplay; import edu.stanford.bmir.protege.web.client.library.msgbox.MessageBox; import edu.stanford.bmir.protege.web.client.projectmanager.ProjectCreatedEvent; -import edu.stanford.bmir.protege.web.client.upload.FileUploadFileReader; +import edu.stanford.bmir.protege.web.client.upload.FileUploader; import edu.stanford.bmir.protege.web.client.user.LoggedInUserManager; import edu.stanford.bmir.protege.web.client.uuid.UuidV4; import edu.stanford.bmir.protege.web.shared.csv.DocumentId; +import edu.stanford.bmir.protege.web.shared.dispatch.actions.GetUserInfoAction; +import edu.stanford.bmir.protege.web.shared.dispatch.actions.GetUserInfoResult; import edu.stanford.bmir.protege.web.shared.permissions.PermissionDeniedException; import edu.stanford.bmir.protege.web.shared.project.*; import edu.stanford.bmir.protege.web.shared.upload.SubmitFileAction; @@ -118,32 +120,35 @@ private void createEmptyProject(ProjectCreatedHandler projectCreatedHandler) { private void uploadSourcesAndCreateProject(@Nonnull ProjectCreatedHandler projectCreatedHandler) { checkNotNull(projectCreatedHandler); - String fileUploadElementId = view.getFileUploadElementId(); - FileUploadFileReader fileUploadFileReader = new FileUploadFileReader(); progressDisplay.displayProgress("Uploading file", "Uploading file. Please wait."); - fileUploadFileReader.readFiles(fileUploadElementId, fileContent -> { - progressDisplay.hideProgress(); - handleFileReadComplete(fileContent, projectCreatedHandler); - }, readError -> { - progressDisplay.hideProgress(); - messageBox.showAlert("Upload Failed", "Your file could not be uploaded."); - }); + dispatchServiceManager.execute(new GetUserInfoAction(), + info -> createProjectForUser(info, projectCreatedHandler)); } - private void handleFileReadComplete(@Nonnull String base64EncodedContent, - ProjectCreatedHandler projectCreatedHandler) { + private void createProjectForUser(GetUserInfoResult userInfo, + ProjectCreatedHandler projectCreatedHandler) { - dispatchServiceManager.execute(SubmitFileAction.create(base64EncodedContent), - busy -> {}, - result -> { - handleCreateNewProjectFromUploadedSources(projectCreatedHandler, result); - }); + String fileUploadElementId = view.getFileUploadElementId(); + FileUploader fileUploader = new FileUploader(); + fileUploader.uploadFile(fileUploadElementId, + userInfo.getToken(), + fileSubmissionId -> handleFileSubmissionSuccess(projectCreatedHandler, fileSubmissionId), + this::handleFileSubmissionError); + } + private void handleFileSubmissionError(int errorCode) { + messageBox.showMessage("Could not upload file", "Error code: " + errorCode); + progressDisplay.hideProgress(); + } + private void handleFileSubmissionSuccess(CreateNewProjectPresenter.ProjectCreatedHandler projectCreatedHandler, + String fileSubmissionId) { + progressDisplay.hideProgress(); + handleCreateNewProjectFromUploadedSources(projectCreatedHandler, + new DocumentId(fileSubmissionId)); } - private void handleCreateNewProjectFromUploadedSources(ProjectCreatedHandler projectCreatedHandler, SubmitFileResult result) { - DocumentId documentId = result.getFileSubmissionId(); + private void handleCreateNewProjectFromUploadedSources(ProjectCreatedHandler projectCreatedHandler, DocumentId documentId) { NewProjectSettings newProjectSettings = NewProjectSettings.get(loggedInUserManager.getLoggedInUserId(), view.getProjectName(), view.getProjectLanguage(), @@ -199,8 +204,4 @@ else if (cause instanceof ProjectDocumentExistsException) { } }); } - - public NewProjectInfo getNewProjectInfo() { - return new NewProjectInfo(view.getProjectName(), view.getProjectDescription()); - } } diff --git a/webprotege-gwt-ui-client/src/main/java/edu/stanford/bmir/protege/web/client/upload/FileUploadErrorHandler.java b/webprotege-gwt-ui-client/src/main/java/edu/stanford/bmir/protege/web/client/upload/FileUploadErrorHandler.java new file mode 100644 index 000000000..cd8e80538 --- /dev/null +++ b/webprotege-gwt-ui-client/src/main/java/edu/stanford/bmir/protege/web/client/upload/FileUploadErrorHandler.java @@ -0,0 +1,11 @@ +package edu.stanford.bmir.protege.web.client.upload; + +/** + * Matthew Horridge + * Stanford Center for Biomedical Informatics Research + * 2024-06-10 + */ +public interface FileUploadErrorHandler { + + void handleFileUploadError(int statusCode); +} diff --git a/webprotege-gwt-ui-client/src/main/java/edu/stanford/bmir/protege/web/client/upload/FileUploadSuccessHandler.java b/webprotege-gwt-ui-client/src/main/java/edu/stanford/bmir/protege/web/client/upload/FileUploadSuccessHandler.java new file mode 100644 index 000000000..6fceb7941 --- /dev/null +++ b/webprotege-gwt-ui-client/src/main/java/edu/stanford/bmir/protege/web/client/upload/FileUploadSuccessHandler.java @@ -0,0 +1,11 @@ +package edu.stanford.bmir.protege.web.client.upload; + +/** + * Matthew Horridge + * Stanford Center for Biomedical Informatics Research + * 2024-06-10 + */ +public interface FileUploadSuccessHandler { + + void handleFileUploadSuccess(String fileSubmissionId); +} diff --git a/webprotege-gwt-ui-client/src/main/java/edu/stanford/bmir/protege/web/client/upload/FileUploader.java b/webprotege-gwt-ui-client/src/main/java/edu/stanford/bmir/protege/web/client/upload/FileUploader.java new file mode 100644 index 000000000..97bb68bee --- /dev/null +++ b/webprotege-gwt-ui-client/src/main/java/edu/stanford/bmir/protege/web/client/upload/FileUploader.java @@ -0,0 +1,58 @@ +package edu.stanford.bmir.protege.web.client.upload; + +/** + * Matthew Horridge + * Stanford Center for Biomedical Informatics Research + * 2024-06-10 + */ +public class FileUploader { + + private static final String END_POINT = "/files/submit"; + + /** + * Upload a file that is retrieved from a FileInput element + * @param fileInputId The Id of the file input element + * @param token The authentication token to use when uploading the file + * @param successHandler The handler that will be called if the upload succeeds. + * @param errorHandler The handle that will be called if the upload fails. + */ + public void uploadFile(String fileInputId, + String token, + FileUploadSuccessHandler successHandler, + FileUploadErrorHandler errorHandler) { + uploadFileNative(fileInputId, END_POINT, token, successHandler, errorHandler); + } + + private native void uploadFileNative(String fileInputId, String endPoint, String token, + FileUploadSuccessHandler successHandler, + FileUploadErrorHandler errorHandler)/*-{ + + var fileElement = $doc.getElementById(fileInputId); + var file = fileElement.files[0]; + + var formData = new FormData(); + formData.append("file", file); + + var xhr = new XMLHttpRequest(); + xhr.open("POST", endPoint, true); + var authHeader = "bearer " + token; + xhr.setRequestHeader('Authorization', authHeader); + xhr.onreadystatechange = function () { + if (xhr.readyState === 4) { + if(xhr.status === 200) { + var submissionId = xhr.responseText.substring(1, xhr.responseText.length - 1); + successHandler.@edu.stanford.bmir.protege.web.client.upload.FileUploadSuccessHandler::handleFileUploadSuccess(*)(submissionId); + } + else { + var errorCode = xhr.status; + errorHandler.@edu.stanford.bmir.protege.web.client.upload.FileUploadErrorHandler::handleFileUploadError(*)(errorCode); + } + } + }; + + console.log("About to send form data"); + // Initiate a multipart/form-data upload + xhr.send(formData); + + }-*/; +} diff --git a/webprotege-gwt-ui-client/src/main/java/edu/stanford/bmir/protege/web/client/upload/UploadFileDialogController.java b/webprotege-gwt-ui-client/src/main/java/edu/stanford/bmir/protege/web/client/upload/UploadFileDialogController.java index 34ce59d2e..5397c3f9d 100644 --- a/webprotege-gwt-ui-client/src/main/java/edu/stanford/bmir/protege/web/client/upload/UploadFileDialogController.java +++ b/webprotege-gwt-ui-client/src/main/java/edu/stanford/bmir/protege/web/client/upload/UploadFileDialogController.java @@ -2,18 +2,15 @@ import com.google.auto.factory.AutoFactory; import com.google.auto.factory.Provided; -import com.google.gwt.core.client.GWT; -import com.google.gwt.user.client.ui.FormPanel; import com.google.gwt.user.client.ui.Widget; import edu.stanford.bmir.protege.web.client.dispatch.DispatchErrorMessageDisplay; -import edu.stanford.bmir.protege.web.client.dispatch.DispatchServiceCallbackWithProgressDisplay; import edu.stanford.bmir.protege.web.client.dispatch.DispatchServiceManager; import edu.stanford.bmir.protege.web.client.dispatch.ProgressDisplay; import edu.stanford.bmir.protege.web.client.library.dlg.*; -import edu.stanford.bmir.protege.web.client.progress.ProgressMonitor; import edu.stanford.bmir.protege.web.client.uuid.UuidV4; -import edu.stanford.bmir.protege.web.shared.upload.SubmitFileAction; -import edu.stanford.bmir.protege.web.shared.upload.SubmitFileResult; +import edu.stanford.bmir.protege.web.shared.csv.DocumentId; +import edu.stanford.bmir.protege.web.shared.dispatch.actions.GetUserInfoAction; +import edu.stanford.bmir.protege.web.shared.dispatch.actions.GetUserInfoResult; import javax.annotation.Nonnull; @@ -29,8 +26,6 @@ public class UploadFileDialogController extends WebProtegeOKCancelDialogControll private final DispatchServiceManager dispatch; - private final DispatchErrorMessageDisplay errorMessageDisplay; - private final ProgressDisplay progressDisplay; private UploadFileDialogForm form = new UploadFileDialogForm(); @@ -42,46 +37,29 @@ public UploadFileDialogController(String title, @Provided ProgressDisplay progressDisplay) { super(title); this.dispatch = dispatch; - this.errorMessageDisplay = errorMessageDisplay; this.progressDisplay = progressDisplay; setDialogButtonHandler(DialogButton.OK, (data, closer) -> handleButtonPress(resultHandler, closer)); form.getFileUpload().getElement().setId(UuidV4.uuidv4()); } private void handleButtonPress(UploadFileResultHandler resultHandler, WebProtegeDialogCloser closer) { - ProgressMonitor.get().showProgressMonitor("Preparing file", "Preparing file for upload. Please wait."); - FileUploadFileReader reader = new FileUploadFileReader(); - reader.readFiles(form.getFileUpload().getElement().getId(), - content -> { - dispatch.execute(SubmitFileAction.create(content), new DispatchServiceCallbackWithProgressDisplay(errorMessageDisplay, - progressDisplay) { - @Override - public String getProgressDisplayTitle() { - return "Uploading file"; - } - - @Override - public String getProgressDisplayMessage() { - return "Please wait"; - } + progressDisplay.displayProgress("Uploading file", "Uploading file. Please wait."); + dispatch.execute(new GetUserInfoAction(), userInfo -> { + String token = userInfo.getToken(); + String fileUploadId = form.getFileUpload().getElement().getId(); + FileUploader fileUploader = new FileUploader(); + fileUploader.uploadFile(fileUploadId, token, fileSubmissionId -> { + progressDisplay.hideProgress(); + closer.hide(); + resultHandler.handleFileUploaded(new DocumentId(fileSubmissionId)); + }, errorCode -> { + progressDisplay.hideProgress(); + closer.hide(); + resultHandler.handleFileUploadFailed("An error occurred uploading the file. Error code: " + errorCode); + }); + }); - @Override - public void handleSuccess(SubmitFileResult submitFileResult) { - closer.hide(); - resultHandler.handleFileUploaded(submitFileResult.getFileSubmissionId()); - } - @Override - public void handleErrorFinally(Throwable throwable) { - closer.hide(); - resultHandler.handleFileUploadFailed("An error occurred uploading the file: " + throwable.getMessage()); - } - }); - }, - errorHandler -> { - ProgressMonitor.get().hideProgressMonitor(); - resultHandler.handleFileUploadFailed("An error occurred preparing the file for upload"); - }); } @Nonnull From 8014ed2ee086c4555257312597db1c81a038c7d6 Mon Sep 17 00:00:00 2001 From: Matthew Horridge Date: Fri, 14 Jun 2024 09:00:22 -0700 Subject: [PATCH 2/2] Remove logging to console --- .../stanford/bmir/protege/web/client/upload/FileUploader.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/webprotege-gwt-ui-client/src/main/java/edu/stanford/bmir/protege/web/client/upload/FileUploader.java b/webprotege-gwt-ui-client/src/main/java/edu/stanford/bmir/protege/web/client/upload/FileUploader.java index 97bb68bee..8a94fe303 100644 --- a/webprotege-gwt-ui-client/src/main/java/edu/stanford/bmir/protege/web/client/upload/FileUploader.java +++ b/webprotege-gwt-ui-client/src/main/java/edu/stanford/bmir/protege/web/client/upload/FileUploader.java @@ -49,8 +49,6 @@ private native void uploadFileNative(String fileInputId, String endPoint, String } } }; - - console.log("About to send form data"); // Initiate a multipart/form-data upload xhr.send(formData);